diff options
author | Antony Clince Alex <aalex@nvidia.com> | 2018-04-25 00:49:01 -0400 |
---|---|---|
committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2018-05-09 21:25:32 -0400 |
commit | 2a23cd249451c952aaab71eaad6cf5f77d2bc6e2 (patch) | |
tree | c9804d669872cc78ef2eb7d941c443ebec42b674 /drivers/gpu/nvgpu/common | |
parent | 703d00d730d230f9ac9970e7d2d22a7d8f0cd2d1 (diff) |
gpu: nvgpu: refectored sim_readl/sim_writel
refactored sim_readl and sim_writel to use
os-agnostic structures.
converted all sim buffers to the type nvgpu_mem and
replaced all alloc_page and free_page calls with
corresponding nvgpu_dma_alloc/nvgpu_dma_free calls.
JIRA VQRM-2368
Change-Id: Ia9d29119d31f239ed16be932cfd16c334002c727
Signed-off-by: Antony Clince Alex <aalex@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1702050
Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com>
Reviewed-by: Sourab Gupta <sourabg@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/common')
-rw-r--r-- | drivers/gpu/nvgpu/common/linux/sim.c | 174 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/common/linux/sim.h | 11 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/common/linux/sim_pci.c | 170 |
3 files changed, 168 insertions, 187 deletions
diff --git a/drivers/gpu/nvgpu/common/linux/sim.c b/drivers/gpu/nvgpu/common/linux/sim.c index 0e158063..7ab7a153 100644 --- a/drivers/gpu/nvgpu/common/linux/sim.c +++ b/drivers/gpu/nvgpu/common/linux/sim.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. | 2 | * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or modify it | 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, | 5 | * under the terms and conditions of the GNU General Public License, |
@@ -20,47 +20,67 @@ | |||
20 | 20 | ||
21 | #include <nvgpu/log.h> | 21 | #include <nvgpu/log.h> |
22 | #include <nvgpu/linux/vm.h> | 22 | #include <nvgpu/linux/vm.h> |
23 | 23 | #include <nvgpu/bitops.h> | |
24 | #include <nvgpu/nvgpu_mem.h> | ||
25 | #include <nvgpu/dma.h> | ||
24 | #include "gk20a/gk20a.h" | 26 | #include "gk20a/gk20a.h" |
25 | #include "sim.h" | 27 | #include "sim.h" |
26 | 28 | ||
27 | #include <nvgpu/hw/gk20a/hw_sim_gk20a.h> | 29 | #include <nvgpu/hw/gk20a/hw_sim_gk20a.h> |
28 | 30 | ||
29 | static inline void sim_writel(struct sim_gk20a_linux *sim_linux, u32 r, u32 v) | 31 | static inline void sim_writel(struct sim_gk20a *sim, u32 r, u32 v) |
30 | { | 32 | { |
33 | struct sim_gk20a_linux *sim_linux = | ||
34 | container_of(sim, struct sim_gk20a_linux, sim); | ||
35 | |||
31 | writel(v, sim_linux->regs + r); | 36 | writel(v, sim_linux->regs + r); |
32 | } | 37 | } |
33 | 38 | ||
34 | static inline u32 sim_readl(struct sim_gk20a_linux *sim_linux, u32 r) | 39 | static inline u32 sim_readl(struct sim_gk20a *sim, u32 r) |
35 | { | 40 | { |
41 | struct sim_gk20a_linux *sim_linux = | ||
42 | container_of(sim, struct sim_gk20a_linux, sim); | ||
43 | |||
36 | return readl(sim_linux->regs + r); | 44 | return readl(sim_linux->regs + r); |
37 | } | 45 | } |
38 | 46 | ||
39 | static void kunmap_and_free_iopage(void **kvaddr, struct page **page) | 47 | static int gk20a_alloc_sim_buffer(struct gk20a *g, struct nvgpu_mem *mem) |
40 | { | 48 | { |
41 | if (*kvaddr) { | 49 | int err; |
42 | kunmap(*kvaddr); | 50 | |
43 | *kvaddr = NULL; | 51 | err = nvgpu_dma_alloc(g, PAGE_SIZE, mem); |
44 | } | 52 | |
45 | if (*page) { | 53 | if (err) |
46 | __free_page(*page); | 54 | return err; |
47 | *page = NULL; | 55 | /* |
56 | * create a valid cpu_va mapping | ||
57 | */ | ||
58 | nvgpu_mem_begin(g, mem); | ||
59 | |||
60 | return 0; | ||
61 | } | ||
62 | |||
63 | static void gk20a_free_sim_buffer(struct gk20a *g, struct nvgpu_mem *mem) | ||
64 | { | ||
65 | if (nvgpu_mem_is_valid(mem)) { | ||
66 | /* | ||
67 | * invalidate the cpu_va mapping | ||
68 | */ | ||
69 | nvgpu_mem_end(g, mem); | ||
70 | nvgpu_dma_free(g, mem); | ||
48 | } | 71 | } |
72 | |||
73 | memset(mem, 0, sizeof(*mem)); | ||
49 | } | 74 | } |
50 | 75 | ||
51 | static void gk20a_free_sim_support(struct gk20a *g) | 76 | static void gk20a_free_sim_support(struct gk20a *g) |
52 | { | 77 | { |
53 | struct sim_gk20a_linux *sim_linux = | 78 | struct sim_gk20a_linux *sim_linux = |
54 | container_of(g->sim, struct sim_gk20a_linux, sim); | 79 | container_of(g->sim, struct sim_gk20a_linux, sim); |
55 | /* free sim mappings, bfrs */ | ||
56 | kunmap_and_free_iopage(&sim_linux->send_bfr.kvaddr, | ||
57 | &sim_linux->send_bfr.page); | ||
58 | 80 | ||
59 | kunmap_and_free_iopage(&sim_linux->recv_bfr.kvaddr, | 81 | gk20a_free_sim_buffer(g, &sim_linux->send_bfr); |
60 | &sim_linux->recv_bfr.page); | 82 | gk20a_free_sim_buffer(g, &sim_linux->recv_bfr); |
61 | 83 | gk20a_free_sim_buffer(g, &sim_linux->msg_bfr); | |
62 | kunmap_and_free_iopage(&sim_linux->msg_bfr.kvaddr, | ||
63 | &sim_linux->msg_bfr.page); | ||
64 | } | 84 | } |
65 | 85 | ||
66 | static void gk20a_remove_sim_support(struct sim_gk20a *s) | 86 | static void gk20a_remove_sim_support(struct sim_gk20a *s) |
@@ -70,7 +90,7 @@ static void gk20a_remove_sim_support(struct sim_gk20a *s) | |||
70 | container_of(g->sim, struct sim_gk20a_linux, sim); | 90 | container_of(g->sim, struct sim_gk20a_linux, sim); |
71 | 91 | ||
72 | if (sim_linux->regs) | 92 | if (sim_linux->regs) |
73 | sim_writel(sim_linux, sim_config_r(), sim_config_mode_disabled_v()); | 93 | sim_writel(s, sim_config_r(), sim_config_mode_disabled_v()); |
74 | gk20a_free_sim_support(g); | 94 | gk20a_free_sim_support(g); |
75 | 95 | ||
76 | if (sim_linux->regs) { | 96 | if (sim_linux->regs) { |
@@ -82,35 +102,6 @@ static void gk20a_remove_sim_support(struct sim_gk20a *s) | |||
82 | g->sim = NULL; | 102 | g->sim = NULL; |
83 | } | 103 | } |
84 | 104 | ||
85 | static int alloc_and_kmap_iopage(struct gk20a *g, | ||
86 | void **kvaddr, | ||
87 | u64 *phys, | ||
88 | struct page **page) | ||
89 | { | ||
90 | int err = 0; | ||
91 | *page = alloc_page(GFP_KERNEL); | ||
92 | |||
93 | if (!*page) { | ||
94 | err = -ENOMEM; | ||
95 | nvgpu_err(g, "couldn't allocate io page"); | ||
96 | goto fail; | ||
97 | } | ||
98 | |||
99 | *kvaddr = kmap(*page); | ||
100 | if (!*kvaddr) { | ||
101 | err = -ENOMEM; | ||
102 | nvgpu_err(g, "couldn't kmap io page"); | ||
103 | goto fail; | ||
104 | } | ||
105 | *phys = page_to_phys(*page); | ||
106 | return 0; | ||
107 | |||
108 | fail: | ||
109 | kunmap_and_free_iopage(kvaddr, page); | ||
110 | return err; | ||
111 | |||
112 | } | ||
113 | |||
114 | static inline u32 sim_msg_header_size(void) | 105 | static inline u32 sim_msg_header_size(void) |
115 | { | 106 | { |
116 | return 24;/*TBD: fix the header to gt this from NV_VGPU_MSG_HEADER*/ | 107 | return 24;/*TBD: fix the header to gt this from NV_VGPU_MSG_HEADER*/ |
@@ -120,7 +111,11 @@ static inline u32 *sim_msg_bfr(struct gk20a *g, u32 byte_offset) | |||
120 | { | 111 | { |
121 | struct sim_gk20a_linux *sim_linux = | 112 | struct sim_gk20a_linux *sim_linux = |
122 | container_of(g->sim, struct sim_gk20a_linux, sim); | 113 | container_of(g->sim, struct sim_gk20a_linux, sim); |
123 | return (u32 *)(sim_linux->msg_bfr.kvaddr + byte_offset); | 114 | u8 *cpu_va; |
115 | |||
116 | cpu_va = (u8 *)sim_linux->msg_bfr.cpu_va; | ||
117 | |||
118 | return (u32 *)(cpu_va + byte_offset); | ||
124 | } | 119 | } |
125 | 120 | ||
126 | static inline u32 *sim_msg_hdr(struct gk20a *g, u32 byte_offset) | 121 | static inline u32 *sim_msg_hdr(struct gk20a *g, u32 byte_offset) |
@@ -153,7 +148,11 @@ static u32 *sim_send_ring_bfr(struct gk20a *g, u32 byte_offset) | |||
153 | { | 148 | { |
154 | struct sim_gk20a_linux *sim_linux = | 149 | struct sim_gk20a_linux *sim_linux = |
155 | container_of(g->sim, struct sim_gk20a_linux, sim); | 150 | container_of(g->sim, struct sim_gk20a_linux, sim); |
156 | return (u32 *)(sim_linux->send_bfr.kvaddr + byte_offset); | 151 | u8 *cpu_va; |
152 | |||
153 | cpu_va = (u8 *)sim_linux->send_bfr.cpu_va; | ||
154 | |||
155 | return (u32 *)(cpu_va + byte_offset); | ||
157 | } | 156 | } |
158 | 157 | ||
159 | static int rpc_send_message(struct gk20a *g) | 158 | static int rpc_send_message(struct gk20a *g) |
@@ -169,18 +168,17 @@ static int rpc_send_message(struct gk20a *g) | |||
169 | sim_dma_target_phys_pci_coherent_f() | | 168 | sim_dma_target_phys_pci_coherent_f() | |
170 | sim_dma_status_valid_f() | | 169 | sim_dma_status_valid_f() | |
171 | sim_dma_size_4kb_f() | | 170 | sim_dma_size_4kb_f() | |
172 | sim_dma_addr_lo_f(sim_linux->msg_bfr.phys >> PAGE_SHIFT); | 171 | sim_dma_addr_lo_f(nvgpu_mem_get_addr(g, &sim_linux->msg_bfr) >> PAGE_SHIFT); |
173 | 172 | ||
174 | *sim_send_ring_bfr(g, dma_hi_offset*sizeof(u32)) = | 173 | *sim_send_ring_bfr(g, dma_hi_offset*sizeof(u32)) = |
175 | u64_hi32(sim_linux->msg_bfr.phys); | 174 | u64_hi32(nvgpu_mem_get_addr(g, &sim_linux->msg_bfr)); |
176 | 175 | ||
177 | *sim_msg_hdr(g, sim_msg_sequence_r()) = g->sim->sequence_base++; | 176 | *sim_msg_hdr(g, sim_msg_sequence_r()) = g->sim->sequence_base++; |
178 | 177 | ||
179 | g->sim->send_ring_put = (g->sim->send_ring_put + 2 * sizeof(u32)) % | 178 | g->sim->send_ring_put = (g->sim->send_ring_put + 2 * sizeof(u32)) % PAGE_SIZE; |
180 | PAGE_SIZE; | ||
181 | 179 | ||
182 | /* Update the put pointer. This will trap into the host. */ | 180 | /* Update the put pointer. This will trap into the host. */ |
183 | sim_writel(sim_linux, sim_send_put_r(), g->sim->send_ring_put); | 181 | sim_writel(g->sim, sim_send_put_r(), g->sim->send_ring_put); |
184 | 182 | ||
185 | return 0; | 183 | return 0; |
186 | } | 184 | } |
@@ -189,7 +187,11 @@ static inline u32 *sim_recv_ring_bfr(struct gk20a *g, u32 byte_offset) | |||
189 | { | 187 | { |
190 | struct sim_gk20a_linux *sim_linux = | 188 | struct sim_gk20a_linux *sim_linux = |
191 | container_of(g->sim, struct sim_gk20a_linux, sim); | 189 | container_of(g->sim, struct sim_gk20a_linux, sim); |
192 | return (u32 *)(sim_linux->recv_bfr.kvaddr + byte_offset); | 190 | u8 *cpu_va; |
191 | |||
192 | cpu_va = (u8 *)sim_linux->recv_bfr.cpu_va; | ||
193 | |||
194 | return (u32 *)(cpu_va + byte_offset); | ||
193 | } | 195 | } |
194 | 196 | ||
195 | static int rpc_recv_poll(struct gk20a *g) | 197 | static int rpc_recv_poll(struct gk20a *g) |
@@ -203,7 +205,7 @@ static int rpc_recv_poll(struct gk20a *g) | |||
203 | 205 | ||
204 | /* Poll the recv ring get pointer in an infinite loop*/ | 206 | /* Poll the recv ring get pointer in an infinite loop*/ |
205 | do { | 207 | do { |
206 | g->sim->recv_ring_put = sim_readl(sim_linux, sim_recv_put_r()); | 208 | g->sim->recv_ring_put = sim_readl(g->sim, sim_recv_put_r()); |
207 | } while (g->sim->recv_ring_put == g->sim->recv_ring_get); | 209 | } while (g->sim->recv_ring_put == g->sim->recv_ring_get); |
208 | 210 | ||
209 | /* process all replies */ | 211 | /* process all replies */ |
@@ -220,19 +222,19 @@ static int rpc_recv_poll(struct gk20a *g) | |||
220 | recv_phys_addr = (u64)recv_phys_addr_hi << 32 | | 222 | recv_phys_addr = (u64)recv_phys_addr_hi << 32 | |
221 | (u64)recv_phys_addr_lo << PAGE_SHIFT; | 223 | (u64)recv_phys_addr_lo << PAGE_SHIFT; |
222 | 224 | ||
223 | if (recv_phys_addr != sim_linux->msg_bfr.phys) { | 225 | if (recv_phys_addr != |
226 | nvgpu_mem_get_addr(g, &sim_linux->msg_bfr)) { | ||
224 | nvgpu_err(g, "%s Error in RPC reply", | 227 | nvgpu_err(g, "%s Error in RPC reply", |
225 | __func__); | 228 | __func__); |
226 | return -1; | 229 | return -1; |
227 | } | 230 | } |
228 | 231 | ||
229 | /* Update GET pointer */ | 232 | /* Update GET pointer */ |
230 | g->sim->recv_ring_get = (g->sim->recv_ring_get + 2*sizeof(u32)) % | 233 | g->sim->recv_ring_get = (g->sim->recv_ring_get + 2*sizeof(u32)) % PAGE_SIZE; |
231 | PAGE_SIZE; | ||
232 | 234 | ||
233 | sim_writel(sim_linux, sim_recv_get_r(), g->sim->recv_ring_get); | 235 | sim_writel(g->sim, sim_recv_get_r(), g->sim->recv_ring_get); |
234 | 236 | ||
235 | g->sim->recv_ring_put = sim_readl(sim_linux, sim_recv_put_r()); | 237 | g->sim->recv_ring_put = sim_readl(g->sim, sim_recv_put_r()); |
236 | } | 238 | } |
237 | 239 | ||
238 | return 0; | 240 | return 0; |
@@ -295,53 +297,41 @@ int gk20a_init_sim_support(struct gk20a *g) | |||
295 | container_of(g->sim, struct sim_gk20a_linux, sim); | 297 | container_of(g->sim, struct sim_gk20a_linux, sim); |
296 | 298 | ||
297 | /* allocate sim event/msg buffers */ | 299 | /* allocate sim event/msg buffers */ |
298 | err = alloc_and_kmap_iopage(g, &sim_linux->send_bfr.kvaddr, | 300 | err = gk20a_alloc_sim_buffer(g, &sim_linux->send_bfr); |
299 | &sim_linux->send_bfr.phys, | 301 | err = err || gk20a_alloc_sim_buffer(g, &sim_linux->recv_bfr); |
300 | &sim_linux->send_bfr.page); | 302 | err = err || gk20a_alloc_sim_buffer(g, &sim_linux->msg_bfr); |
301 | |||
302 | err = err || alloc_and_kmap_iopage(g, &sim_linux->recv_bfr.kvaddr, | ||
303 | &sim_linux->recv_bfr.phys, | ||
304 | &sim_linux->recv_bfr.page); | ||
305 | |||
306 | err = err || alloc_and_kmap_iopage(g, &sim_linux->msg_bfr.kvaddr, | ||
307 | &sim_linux->msg_bfr.phys, | ||
308 | &sim_linux->msg_bfr.page); | ||
309 | 303 | ||
310 | if (!(sim_linux->send_bfr.kvaddr && sim_linux->recv_bfr.kvaddr && | 304 | if (err) |
311 | sim_linux->msg_bfr.kvaddr)) { | ||
312 | nvgpu_err(g, "couldn't allocate all sim buffers"); | ||
313 | goto fail; | 305 | goto fail; |
314 | } | ||
315 | |||
316 | /*mark send ring invalid*/ | 306 | /*mark send ring invalid*/ |
317 | sim_writel(sim_linux, sim_send_ring_r(), sim_send_ring_status_invalid_f()); | 307 | sim_writel(g->sim, sim_send_ring_r(), sim_send_ring_status_invalid_f()); |
318 | 308 | ||
319 | /*read get pointer and make equal to put*/ | 309 | /*read get pointer and make equal to put*/ |
320 | g->sim->send_ring_put = sim_readl(sim_linux, sim_send_get_r()); | 310 | g->sim->send_ring_put = sim_readl(g->sim, sim_send_get_r()); |
321 | sim_writel(sim_linux, sim_send_put_r(), g->sim->send_ring_put); | 311 | sim_writel(g->sim, sim_send_put_r(), g->sim->send_ring_put); |
322 | 312 | ||
323 | /*write send ring address and make it valid*/ | 313 | /*write send ring address and make it valid*/ |
324 | phys = sim_linux->send_bfr.phys; | 314 | phys = nvgpu_mem_get_addr(g, &sim_linux->send_bfr); |
325 | sim_writel(sim_linux, sim_send_ring_hi_r(), | 315 | sim_writel(g->sim, sim_send_ring_hi_r(), |
326 | sim_send_ring_hi_addr_f(u64_hi32(phys))); | 316 | sim_send_ring_hi_addr_f(u64_hi32(phys))); |
327 | sim_writel(sim_linux, sim_send_ring_r(), | 317 | sim_writel(g->sim, sim_send_ring_r(), |
328 | sim_send_ring_status_valid_f() | | 318 | sim_send_ring_status_valid_f() | |
329 | sim_send_ring_target_phys_pci_coherent_f() | | 319 | sim_send_ring_target_phys_pci_coherent_f() | |
330 | sim_send_ring_size_4kb_f() | | 320 | sim_send_ring_size_4kb_f() | |
331 | sim_send_ring_addr_lo_f(phys >> PAGE_SHIFT)); | 321 | sim_send_ring_addr_lo_f(phys >> PAGE_SHIFT)); |
332 | 322 | ||
333 | /*repeat for recv ring (but swap put,get as roles are opposite) */ | 323 | /*repeat for recv ring (but swap put,get as roles are opposite) */ |
334 | sim_writel(sim_linux, sim_recv_ring_r(), sim_recv_ring_status_invalid_f()); | 324 | sim_writel(g->sim, sim_recv_ring_r(), sim_recv_ring_status_invalid_f()); |
335 | 325 | ||
336 | /*read put pointer and make equal to get*/ | 326 | /*read put pointer and make equal to get*/ |
337 | g->sim->recv_ring_get = sim_readl(sim_linux, sim_recv_put_r()); | 327 | g->sim->recv_ring_get = sim_readl(g->sim, sim_recv_put_r()); |
338 | sim_writel(sim_linux, sim_recv_get_r(), g->sim->recv_ring_get); | 328 | sim_writel(g->sim, sim_recv_get_r(), g->sim->recv_ring_get); |
339 | 329 | ||
340 | /*write send ring address and make it valid*/ | 330 | /*write send ring address and make it valid*/ |
341 | phys = sim_linux->recv_bfr.phys; | 331 | phys = nvgpu_mem_get_addr(g, &sim_linux->recv_bfr); |
342 | sim_writel(sim_linux, sim_recv_ring_hi_r(), | 332 | sim_writel(g->sim, sim_recv_ring_hi_r(), |
343 | sim_recv_ring_hi_addr_f(u64_hi32(phys))); | 333 | sim_recv_ring_hi_addr_f(u64_hi32(phys))); |
344 | sim_writel(sim_linux, sim_recv_ring_r(), | 334 | sim_writel(g->sim, sim_recv_ring_r(), |
345 | sim_recv_ring_status_valid_f() | | 335 | sim_recv_ring_status_valid_f() | |
346 | sim_recv_ring_target_phys_pci_coherent_f() | | 336 | sim_recv_ring_target_phys_pci_coherent_f() | |
347 | sim_recv_ring_size_4kb_f() | | 337 | sim_recv_ring_size_4kb_f() | |
diff --git a/drivers/gpu/nvgpu/common/linux/sim.h b/drivers/gpu/nvgpu/common/linux/sim.h index a9ec0dba..4b5e910c 100644 --- a/drivers/gpu/nvgpu/common/linux/sim.h +++ b/drivers/gpu/nvgpu/common/linux/sim.h | |||
@@ -2,7 +2,7 @@ | |||
2 | * | 2 | * |
3 | * GK20A sim support | 3 | * GK20A sim support |
4 | * | 4 | * |
5 | * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. | 5 | * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify it | 7 | * This program is free software; you can redistribute it and/or modify it |
8 | * under the terms and conditions of the GNU General Public License, | 8 | * under the terms and conditions of the GNU General Public License, |
@@ -20,17 +20,16 @@ | |||
20 | #ifndef __SIM_LINUX_H__ | 20 | #ifndef __SIM_LINUX_H__ |
21 | #define __SIM_LINUX_H__ | 21 | #define __SIM_LINUX_H__ |
22 | 22 | ||
23 | #include <nvgpu/nvgpu_mem.h> | ||
23 | #include "gk20a/sim_gk20a.h" | 24 | #include "gk20a/sim_gk20a.h" |
24 | 25 | ||
25 | struct sim_gk20a_linux { | 26 | struct sim_gk20a_linux { |
26 | struct sim_gk20a sim; | 27 | struct sim_gk20a sim; |
27 | struct resource *reg_mem; | 28 | struct resource *reg_mem; |
28 | void __iomem *regs; | 29 | void __iomem *regs; |
29 | struct { | 30 | struct nvgpu_mem send_bfr; |
30 | struct page *page; | 31 | struct nvgpu_mem recv_bfr; |
31 | void *kvaddr; | 32 | struct nvgpu_mem msg_bfr; |
32 | u64 phys; | ||
33 | } send_bfr, recv_bfr, msg_bfr; | ||
34 | }; | 33 | }; |
35 | 34 | ||
36 | int gk20a_init_sim_support(struct gk20a *g); | 35 | int gk20a_init_sim_support(struct gk20a *g); |
diff --git a/drivers/gpu/nvgpu/common/linux/sim_pci.c b/drivers/gpu/nvgpu/common/linux/sim_pci.c index 889eeb24..ea417615 100644 --- a/drivers/gpu/nvgpu/common/linux/sim_pci.c +++ b/drivers/gpu/nvgpu/common/linux/sim_pci.c | |||
@@ -20,47 +20,67 @@ | |||
20 | 20 | ||
21 | #include <nvgpu/log.h> | 21 | #include <nvgpu/log.h> |
22 | #include <nvgpu/linux/vm.h> | 22 | #include <nvgpu/linux/vm.h> |
23 | 23 | #include <nvgpu/bitops.h> | |
24 | #include <nvgpu/nvgpu_mem.h> | ||
25 | #include <nvgpu/dma.h> | ||
24 | #include "gk20a/gk20a.h" | 26 | #include "gk20a/gk20a.h" |
25 | #include "os_linux.h" | 27 | #include "os_linux.h" |
26 | #include "sim.h" | 28 | #include "sim.h" |
27 | #include "hw_sim_pci.h" | 29 | #include "hw_sim_pci.h" |
28 | 30 | ||
29 | static inline void sim_writel(struct sim_gk20a_linux *sim_linux, u32 r, u32 v) | 31 | static inline void sim_writel(struct sim_gk20a *sim, u32 r, u32 v) |
30 | { | 32 | { |
33 | struct sim_gk20a_linux *sim_linux = | ||
34 | container_of(sim, struct sim_gk20a_linux, sim); | ||
35 | |||
31 | writel(v, sim_linux->regs + r); | 36 | writel(v, sim_linux->regs + r); |
32 | } | 37 | } |
33 | 38 | ||
34 | static inline u32 sim_readl(struct sim_gk20a_linux *sim_linux, u32 r) | 39 | static inline u32 sim_readl(struct sim_gk20a *sim, u32 r) |
35 | { | 40 | { |
41 | struct sim_gk20a_linux *sim_linux = | ||
42 | container_of(sim, struct sim_gk20a_linux, sim); | ||
43 | |||
36 | return readl(sim_linux->regs + r); | 44 | return readl(sim_linux->regs + r); |
37 | } | 45 | } |
38 | 46 | ||
39 | static void kunmap_and_free_iopage(void **kvaddr, struct page **page) | 47 | static int gk20a_alloc_sim_buffer(struct gk20a *g, struct nvgpu_mem *mem) |
40 | { | 48 | { |
41 | if (*kvaddr) { | 49 | int err; |
42 | kunmap(*kvaddr); | 50 | |
43 | *kvaddr = NULL; | 51 | err = nvgpu_dma_alloc(g, PAGE_SIZE, mem); |
44 | } | 52 | |
45 | if (*page) { | 53 | if (err) |
46 | __free_page(*page); | 54 | return err; |
47 | *page = NULL; | 55 | /* |
56 | * create a valid cpu_va mapping | ||
57 | */ | ||
58 | nvgpu_mem_begin(g, mem); | ||
59 | |||
60 | return 0; | ||
61 | } | ||
62 | |||
63 | static void gk20a_free_sim_buffer(struct gk20a *g, struct nvgpu_mem *mem) | ||
64 | { | ||
65 | if (nvgpu_mem_is_valid(mem)) { | ||
66 | /* | ||
67 | * invalidate the cpu_va mapping | ||
68 | */ | ||
69 | nvgpu_mem_end(g, mem); | ||
70 | nvgpu_dma_free(g, mem); | ||
48 | } | 71 | } |
72 | |||
73 | memset(mem, 0, sizeof(*mem)); | ||
49 | } | 74 | } |
50 | 75 | ||
51 | static void gk20a_free_sim_support(struct gk20a *g) | 76 | static void gk20a_free_sim_support(struct gk20a *g) |
52 | { | 77 | { |
53 | struct sim_gk20a_linux *sim_linux = | 78 | struct sim_gk20a_linux *sim_linux = |
54 | container_of(g->sim, struct sim_gk20a_linux, sim); | 79 | container_of(g->sim, struct sim_gk20a_linux, sim); |
55 | /* free sim mappings, bfrs */ | ||
56 | kunmap_and_free_iopage(&sim_linux->send_bfr.kvaddr, | ||
57 | &sim_linux->send_bfr.page); | ||
58 | 80 | ||
59 | kunmap_and_free_iopage(&sim_linux->recv_bfr.kvaddr, | 81 | gk20a_free_sim_buffer(g, &sim_linux->send_bfr); |
60 | &sim_linux->recv_bfr.page); | 82 | gk20a_free_sim_buffer(g, &sim_linux->recv_bfr); |
61 | 83 | gk20a_free_sim_buffer(g, &sim_linux->msg_bfr); | |
62 | kunmap_and_free_iopage(&sim_linux->msg_bfr.kvaddr, | ||
63 | &sim_linux->msg_bfr.page); | ||
64 | } | 84 | } |
65 | 85 | ||
66 | static void gk20a_remove_sim_support(struct sim_gk20a *s) | 86 | static void gk20a_remove_sim_support(struct sim_gk20a *s) |
@@ -70,7 +90,7 @@ static void gk20a_remove_sim_support(struct sim_gk20a *s) | |||
70 | container_of(g->sim, struct sim_gk20a_linux, sim); | 90 | container_of(g->sim, struct sim_gk20a_linux, sim); |
71 | 91 | ||
72 | if (sim_linux->regs) | 92 | if (sim_linux->regs) |
73 | sim_writel(sim_linux, sim_config_r(), sim_config_mode_disabled_v()); | 93 | sim_writel(s, sim_config_r(), sim_config_mode_disabled_v()); |
74 | gk20a_free_sim_support(g); | 94 | gk20a_free_sim_support(g); |
75 | 95 | ||
76 | if (sim_linux->regs) { | 96 | if (sim_linux->regs) { |
@@ -82,35 +102,6 @@ static void gk20a_remove_sim_support(struct sim_gk20a *s) | |||
82 | g->sim = NULL; | 102 | g->sim = NULL; |
83 | } | 103 | } |
84 | 104 | ||
85 | static int alloc_and_kmap_iopage(struct gk20a *g, | ||
86 | void **kvaddr, | ||
87 | u64 *phys, | ||
88 | struct page **page) | ||
89 | { | ||
90 | int err = 0; | ||
91 | *page = alloc_page(GFP_KERNEL); | ||
92 | |||
93 | if (!*page) { | ||
94 | err = -ENOMEM; | ||
95 | nvgpu_err(g, "couldn't allocate io page"); | ||
96 | goto fail; | ||
97 | } | ||
98 | |||
99 | *kvaddr = kmap(*page); | ||
100 | if (!*kvaddr) { | ||
101 | err = -ENOMEM; | ||
102 | nvgpu_err(g, "couldn't kmap io page"); | ||
103 | goto fail; | ||
104 | } | ||
105 | *phys = page_to_phys(*page); | ||
106 | return 0; | ||
107 | |||
108 | fail: | ||
109 | kunmap_and_free_iopage(kvaddr, page); | ||
110 | return err; | ||
111 | |||
112 | } | ||
113 | |||
114 | static inline u32 sim_msg_header_size(void) | 105 | static inline u32 sim_msg_header_size(void) |
115 | { | 106 | { |
116 | return 32U; | 107 | return 32U; |
@@ -120,7 +111,11 @@ static inline u32 *sim_msg_bfr(struct gk20a *g, u32 byte_offset) | |||
120 | { | 111 | { |
121 | struct sim_gk20a_linux *sim_linux = | 112 | struct sim_gk20a_linux *sim_linux = |
122 | container_of(g->sim, struct sim_gk20a_linux, sim); | 113 | container_of(g->sim, struct sim_gk20a_linux, sim); |
123 | return (u32 *)(sim_linux->msg_bfr.kvaddr + byte_offset); | 114 | u8 *cpu_va; |
115 | |||
116 | cpu_va = (u8 *)sim_linux->msg_bfr.cpu_va; | ||
117 | |||
118 | return (u32 *)(cpu_va + byte_offset); | ||
124 | } | 119 | } |
125 | 120 | ||
126 | static inline u32 *sim_msg_hdr(struct gk20a *g, u32 byte_offset) | 121 | static inline u32 *sim_msg_hdr(struct gk20a *g, u32 byte_offset) |
@@ -155,7 +150,11 @@ static u32 *sim_send_ring_bfr(struct gk20a *g, u32 byte_offset) | |||
155 | { | 150 | { |
156 | struct sim_gk20a_linux *sim_linux = | 151 | struct sim_gk20a_linux *sim_linux = |
157 | container_of(g->sim, struct sim_gk20a_linux, sim); | 152 | container_of(g->sim, struct sim_gk20a_linux, sim); |
158 | return (u32 *)(sim_linux->send_bfr.kvaddr + byte_offset); | 153 | u8 *cpu_va; |
154 | |||
155 | cpu_va = (u8 *)sim_linux->send_bfr.cpu_va; | ||
156 | |||
157 | return (u32 *)(cpu_va + byte_offset); | ||
159 | } | 158 | } |
160 | 159 | ||
161 | static int rpc_send_message(struct gk20a *g) | 160 | static int rpc_send_message(struct gk20a *g) |
@@ -171,10 +170,10 @@ static int rpc_send_message(struct gk20a *g) | |||
171 | sim_dma_target_phys_pci_coherent_f() | | 170 | sim_dma_target_phys_pci_coherent_f() | |
172 | sim_dma_status_valid_f() | | 171 | sim_dma_status_valid_f() | |
173 | sim_dma_size_4kb_f() | | 172 | sim_dma_size_4kb_f() | |
174 | sim_dma_addr_lo_f(sim_linux->msg_bfr.phys >> PAGE_SHIFT); | 173 | sim_dma_addr_lo_f(nvgpu_mem_get_addr(g, &sim_linux->msg_bfr) >> PAGE_SHIFT); |
175 | 174 | ||
176 | *sim_send_ring_bfr(g, dma_hi_offset*sizeof(u32)) = | 175 | *sim_send_ring_bfr(g, dma_hi_offset*sizeof(u32)) = |
177 | u64_hi32(sim_linux->msg_bfr.phys); | 176 | u64_hi32(nvgpu_mem_get_addr(g, &sim_linux->msg_bfr)); |
178 | 177 | ||
179 | *sim_msg_hdr(g, sim_msg_sequence_r()) = g->sim->sequence_base++; | 178 | *sim_msg_hdr(g, sim_msg_sequence_r()) = g->sim->sequence_base++; |
180 | 179 | ||
@@ -182,7 +181,7 @@ static int rpc_send_message(struct gk20a *g) | |||
182 | PAGE_SIZE; | 181 | PAGE_SIZE; |
183 | 182 | ||
184 | /* Update the put pointer. This will trap into the host. */ | 183 | /* Update the put pointer. This will trap into the host. */ |
185 | sim_writel(sim_linux, sim_send_put_r(), g->sim->send_ring_put); | 184 | sim_writel(g->sim, sim_send_put_r(), g->sim->send_ring_put); |
186 | 185 | ||
187 | return 0; | 186 | return 0; |
188 | } | 187 | } |
@@ -191,7 +190,11 @@ static inline u32 *sim_recv_ring_bfr(struct gk20a *g, u32 byte_offset) | |||
191 | { | 190 | { |
192 | struct sim_gk20a_linux *sim_linux = | 191 | struct sim_gk20a_linux *sim_linux = |
193 | container_of(g->sim, struct sim_gk20a_linux, sim); | 192 | container_of(g->sim, struct sim_gk20a_linux, sim); |
194 | return (u32 *)(sim_linux->recv_bfr.kvaddr + byte_offset); | 193 | u8 *cpu_va; |
194 | |||
195 | cpu_va = (u8 *)sim_linux->recv_bfr.cpu_va; | ||
196 | |||
197 | return (u32 *)(cpu_va + byte_offset); | ||
195 | } | 198 | } |
196 | 199 | ||
197 | static int rpc_recv_poll(struct gk20a *g) | 200 | static int rpc_recv_poll(struct gk20a *g) |
@@ -202,7 +205,7 @@ static int rpc_recv_poll(struct gk20a *g) | |||
202 | 205 | ||
203 | /* Poll the recv ring get pointer in an infinite loop */ | 206 | /* Poll the recv ring get pointer in an infinite loop */ |
204 | do { | 207 | do { |
205 | g->sim->recv_ring_put = sim_readl(sim_linux, sim_recv_put_r()); | 208 | g->sim->recv_ring_put = sim_readl(g->sim, sim_recv_put_r()); |
206 | } while (g->sim->recv_ring_put == g->sim->recv_ring_get); | 209 | } while (g->sim->recv_ring_put == g->sim->recv_ring_get); |
207 | 210 | ||
208 | /* process all replies */ | 211 | /* process all replies */ |
@@ -219,18 +222,19 @@ static int rpc_recv_poll(struct gk20a *g) | |||
219 | recv_phys_addr = (u64)recv_phys_addr_hi << 32 | | 222 | recv_phys_addr = (u64)recv_phys_addr_hi << 32 | |
220 | (u64)recv_phys_addr_lo << PAGE_SHIFT; | 223 | (u64)recv_phys_addr_lo << PAGE_SHIFT; |
221 | 224 | ||
222 | if (recv_phys_addr != sim_linux->msg_bfr.phys) { | 225 | if (recv_phys_addr != |
226 | nvgpu_mem_get_addr(g, &sim_linux->msg_bfr)) { | ||
223 | nvgpu_err(g, "Error in RPC reply"); | 227 | nvgpu_err(g, "Error in RPC reply"); |
224 | return -EINVAL; | 228 | return -EINVAL; |
225 | } | 229 | } |
226 | 230 | ||
227 | /* Update GET pointer */ | 231 | /* Update GET pointer */ |
228 | g->sim->recv_ring_get = (g->sim->recv_ring_get + 2*sizeof(u32)) % | 232 | g->sim->recv_ring_get = (g->sim->recv_ring_get + 2*sizeof(u32)) |
229 | PAGE_SIZE; | 233 | % PAGE_SIZE; |
230 | 234 | ||
231 | sim_writel(sim_linux, sim_recv_get_r(), g->sim->recv_ring_get); | 235 | sim_writel(g->sim, sim_recv_get_r(), g->sim->recv_ring_get); |
232 | 236 | ||
233 | g->sim->recv_ring_put = sim_readl(sim_linux, sim_recv_put_r()); | 237 | g->sim->recv_ring_put = sim_readl(g->sim, sim_recv_put_r()); |
234 | } | 238 | } |
235 | 239 | ||
236 | return 0; | 240 | return 0; |
@@ -316,53 +320,41 @@ int nvgpu_pci_init_sim_support(struct gk20a *g) | |||
316 | sim_linux->regs = l->regs + sim_r(); | 320 | sim_linux->regs = l->regs + sim_r(); |
317 | 321 | ||
318 | /* allocate sim event/msg buffers */ | 322 | /* allocate sim event/msg buffers */ |
319 | err = alloc_and_kmap_iopage(g, &sim_linux->send_bfr.kvaddr, | 323 | err = gk20a_alloc_sim_buffer(g, &sim_linux->send_bfr); |
320 | &sim_linux->send_bfr.phys, | 324 | err = err || gk20a_alloc_sim_buffer(g, &sim_linux->recv_bfr); |
321 | &sim_linux->send_bfr.page); | 325 | err = err || gk20a_alloc_sim_buffer(g, &sim_linux->msg_bfr); |
322 | |||
323 | err = err || alloc_and_kmap_iopage(g, &sim_linux->recv_bfr.kvaddr, | ||
324 | &sim_linux->recv_bfr.phys, | ||
325 | &sim_linux->recv_bfr.page); | ||
326 | |||
327 | err = err || alloc_and_kmap_iopage(g, &sim_linux->msg_bfr.kvaddr, | ||
328 | &sim_linux->msg_bfr.phys, | ||
329 | &sim_linux->msg_bfr.page); | ||
330 | 326 | ||
331 | if (!(sim_linux->send_bfr.kvaddr && sim_linux->recv_bfr.kvaddr && | 327 | if (err) |
332 | sim_linux->msg_bfr.kvaddr)) { | ||
333 | nvgpu_err(g, "couldn't allocate all sim buffers"); | ||
334 | goto fail; | 328 | goto fail; |
335 | } | ||
336 | |||
337 | /* mark send ring invalid */ | 329 | /* mark send ring invalid */ |
338 | sim_writel(sim_linux, sim_send_ring_r(), sim_send_ring_status_invalid_f()); | 330 | sim_writel(g->sim, sim_send_ring_r(), sim_send_ring_status_invalid_f()); |
339 | 331 | ||
340 | /* read get pointer and make equal to put */ | 332 | /* read get pointer and make equal to put */ |
341 | g->sim->send_ring_put = sim_readl(sim_linux, sim_send_get_r()); | 333 | g->sim->send_ring_put = sim_readl(g->sim, sim_send_get_r()); |
342 | sim_writel(sim_linux, sim_send_put_r(), g->sim->send_ring_put); | 334 | sim_writel(g->sim, sim_send_put_r(), g->sim->send_ring_put); |
343 | 335 | ||
344 | /* write send ring address and make it valid */ | 336 | /* write send ring address and make it valid */ |
345 | phys = sim_linux->send_bfr.phys; | 337 | phys = nvgpu_mem_get_addr(g, &sim_linux->send_bfr); |
346 | sim_writel(sim_linux, sim_send_ring_hi_r(), | 338 | sim_writel(g->sim, sim_send_ring_hi_r(), |
347 | sim_send_ring_hi_addr_f(u64_hi32(phys))); | 339 | sim_send_ring_hi_addr_f(u64_hi32(phys))); |
348 | sim_writel(sim_linux, sim_send_ring_r(), | 340 | sim_writel(g->sim, sim_send_ring_r(), |
349 | sim_send_ring_status_valid_f() | | 341 | sim_send_ring_status_valid_f() | |
350 | sim_send_ring_target_phys_pci_coherent_f() | | 342 | sim_send_ring_target_phys_pci_coherent_f() | |
351 | sim_send_ring_size_4kb_f() | | 343 | sim_send_ring_size_4kb_f() | |
352 | sim_send_ring_addr_lo_f(phys >> PAGE_SHIFT)); | 344 | sim_send_ring_addr_lo_f(phys >> PAGE_SHIFT)); |
353 | 345 | ||
354 | /* repeat for recv ring (but swap put,get as roles are opposite) */ | 346 | /* repeat for recv ring (but swap put,get as roles are opposite) */ |
355 | sim_writel(sim_linux, sim_recv_ring_r(), sim_recv_ring_status_invalid_f()); | 347 | sim_writel(g->sim, sim_recv_ring_r(), sim_recv_ring_status_invalid_f()); |
356 | 348 | ||
357 | /* read put pointer and make equal to get */ | 349 | /* read put pointer and make equal to get */ |
358 | g->sim->recv_ring_get = sim_readl(sim_linux, sim_recv_put_r()); | 350 | g->sim->recv_ring_get = sim_readl(g->sim, sim_recv_put_r()); |
359 | sim_writel(sim_linux, sim_recv_get_r(), g->sim->recv_ring_get); | 351 | sim_writel(g->sim, sim_recv_get_r(), g->sim->recv_ring_get); |
360 | 352 | ||
361 | /* write send ring address and make it valid */ | 353 | /* write send ring address and make it valid */ |
362 | phys = sim_linux->recv_bfr.phys; | 354 | phys = nvgpu_mem_get_addr(g, &sim_linux->recv_bfr); |
363 | sim_writel(sim_linux, sim_recv_ring_hi_r(), | 355 | sim_writel(g->sim, sim_recv_ring_hi_r(), |
364 | sim_recv_ring_hi_addr_f(u64_hi32(phys))); | 356 | sim_recv_ring_hi_addr_f(u64_hi32(phys))); |
365 | sim_writel(sim_linux, sim_recv_ring_r(), | 357 | sim_writel(g->sim, sim_recv_ring_r(), |
366 | sim_recv_ring_status_valid_f() | | 358 | sim_recv_ring_status_valid_f() | |
367 | sim_recv_ring_target_phys_pci_coherent_f() | | 359 | sim_recv_ring_target_phys_pci_coherent_f() | |
368 | sim_recv_ring_size_4kb_f() | | 360 | sim_recv_ring_size_4kb_f() | |