summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMahantesh Kumbar <mkumbar@nvidia.com>2018-07-11 05:30:45 -0400
committermobile promotions <svcmobile_promotions@nvidia.com>2018-07-31 04:25:41 -0400
commit2d454db04fcc0c03e05b4665831e5780240d79b8 (patch)
treec18fd4bc302ea68e57e1e1d95c0f253e800bc043
parentd32692ae2427693daf85b3c7b4e24cd36471dec6 (diff)
gpu: nvgpu: falcon queue support
-Renamed "struct pmu_queue" to "struct nvgpu_falcon_queue" & moved to falcon.h -Renamed pmu_queue_* functions to flcn_queue_* & moved to new file falcon_queue.c -Created ops for queue functions in struct nvgpu_falcon_queue to support different queue types like DMEM/FB-Q. -Created ops in nvgpu_falcon_engine_dependency_ops to add engine specific queue functionality & assigned correct HAL functions in hal*.c file. -Made changes in dependent functions as needed to replace struct pmu_queue & calling queue functions using nvgpu_falcon_queue data structure. -Replaced input param "struct nvgpu_pmu *pmu" with "struct gk20a *g" for pmu ops pmu_queue_head/pmu_queue_tail & also for functions gk20a_pmu_queue_head()/ gk20a_pmu_queue_tail(). -Made changes in nvgpu_pmu_queue_init() to use nvgpu_falcon_queue for PMU queue. -Modified Makefile to include falcon_queue.o -Modified Makefile.sources to include falcon_queue.c Change-Id: I956328f6631b7154267fd5a29eaa1826190d99d1 Signed-off-by: Mahantesh Kumbar <mkumbar@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/1776070 Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
-rw-r--r--drivers/gpu/nvgpu/Makefile1
-rw-r--r--drivers/gpu/nvgpu/Makefile.sources1
-rw-r--r--drivers/gpu/nvgpu/common/falcon/falcon_queue.c422
-rw-r--r--drivers/gpu/nvgpu/common/pmu/pmu.c5
-rw-r--r--drivers/gpu/nvgpu/common/pmu/pmu_fw.c12
-rw-r--r--drivers/gpu/nvgpu/common/pmu/pmu_ipc.c353
-rw-r--r--drivers/gpu/nvgpu/gk20a/flcn_gk20a.c3
-rw-r--r--drivers/gpu/nvgpu/gk20a/gk20a.h10
-rw-r--r--drivers/gpu/nvgpu/gk20a/pmu_gk20a.c11
-rw-r--r--drivers/gpu/nvgpu/gk20a/pmu_gk20a.h4
-rw-r--r--drivers/gpu/nvgpu/gp106/flcn_gp106.c3
-rw-r--r--drivers/gpu/nvgpu/include/nvgpu/falcon.h58
-rw-r--r--drivers/gpu/nvgpu/include/nvgpu/pmu.h28
-rw-r--r--drivers/gpu/nvgpu/include/nvgpu/pmuif/gpmuif_cmn.h18
14 files changed, 567 insertions, 362 deletions
diff --git a/drivers/gpu/nvgpu/Makefile b/drivers/gpu/nvgpu/Makefile
index aa780f55..a7b73c81 100644
--- a/drivers/gpu/nvgpu/Makefile
+++ b/drivers/gpu/nvgpu/Makefile
@@ -170,6 +170,7 @@ nvgpu-y += \
170 common/rbtree.o \ 170 common/rbtree.o \
171 common/vbios/bios.o \ 171 common/vbios/bios.o \
172 common/falcon/falcon.o \ 172 common/falcon/falcon.o \
173 common/falcon/falcon_queue.o \
173 common/pmu/pmu.o \ 174 common/pmu/pmu.o \
174 common/pmu/pmu_ipc.o \ 175 common/pmu/pmu_ipc.o \
175 common/pmu/pmu_fw.o \ 176 common/pmu/pmu_fw.o \
diff --git a/drivers/gpu/nvgpu/Makefile.sources b/drivers/gpu/nvgpu/Makefile.sources
index 8095f6ba..942b6681 100644
--- a/drivers/gpu/nvgpu/Makefile.sources
+++ b/drivers/gpu/nvgpu/Makefile.sources
@@ -52,6 +52,7 @@ srcs := common/mm/nvgpu_allocator.c \
52 common/ecc.c \ 52 common/ecc.c \
53 common/vbios/bios.c \ 53 common/vbios/bios.c \
54 common/falcon/falcon.c \ 54 common/falcon/falcon.c \
55 common/falcon/falcon_queue.c \
55 common/pmu/pmu.c \ 56 common/pmu/pmu.c \
56 common/pmu/pmu_ipc.c \ 57 common/pmu/pmu_ipc.c \
57 common/pmu/pmu_fw.c \ 58 common/pmu/pmu_fw.c \
diff --git a/drivers/gpu/nvgpu/common/falcon/falcon_queue.c b/drivers/gpu/nvgpu/common/falcon/falcon_queue.c
new file mode 100644
index 00000000..6834821c
--- /dev/null
+++ b/drivers/gpu/nvgpu/common/falcon/falcon_queue.c
@@ -0,0 +1,422 @@
1/*
2 * Copyright (c) 2017-2018, 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
23#include <nvgpu/lock.h>
24#include <nvgpu/timers.h>
25#include <nvgpu/pmu.h>
26#include <nvgpu/falcon.h>
27
28/* DMEM-Q specific ops */
29static int flcn_queue_head_dmem(struct nvgpu_falcon *flcn,
30 struct nvgpu_falcon_queue *queue, u32 *head, bool set)
31{
32 int err = -ENOSYS;
33
34 if (flcn->flcn_engine_dep_ops.queue_head != NULL) {
35 err = flcn->flcn_engine_dep_ops.queue_head(flcn->g, queue,
36 head, set);
37 }
38
39 return err;
40}
41
42static int flcn_queue_tail_dmem(struct nvgpu_falcon *flcn,
43 struct nvgpu_falcon_queue *queue, u32 *tail, bool set)
44{
45 int err = -ENOSYS;
46
47 if (flcn->flcn_engine_dep_ops.queue_tail != NULL) {
48 err = flcn->flcn_engine_dep_ops.queue_tail(flcn->g, queue,
49 tail, set);
50 }
51
52 return err;
53}
54
55static bool flcn_queue_has_room_dmem(struct nvgpu_falcon *flcn,
56 struct nvgpu_falcon_queue *queue, u32 size, bool *need_rewind)
57{
58 u32 q_head = 0;
59 u32 q_tail = 0;
60 u32 q_free = 0;
61 bool q_rewind = false;
62 int err = 0;
63
64 size = ALIGN(size, QUEUE_ALIGNMENT);
65
66 err = queue->head(flcn, queue, &q_head, QUEUE_GET);
67 if (err != 0) {
68 nvgpu_err(flcn->g, "queue head GET failed");
69 goto exit;
70 }
71
72 err = queue->tail(flcn, queue, &q_tail, QUEUE_GET);
73 if (err != 0) {
74 nvgpu_err(flcn->g, "queue tail GET failed");
75 goto exit;
76 }
77
78 if (q_head >= q_tail) {
79 q_free = queue->offset + queue->size - q_head;
80 q_free -= (u32)PMU_CMD_HDR_SIZE;
81
82 if (size > q_free) {
83 q_rewind = true;
84 q_head = queue->offset;
85 }
86 }
87
88 if (q_head < q_tail) {
89 q_free = q_tail - q_head - 1U;
90 }
91
92 if (need_rewind != NULL) {
93 *need_rewind = q_rewind;
94 }
95
96exit:
97 return size <= q_free;
98}
99
100static int flcn_queue_push_dmem(struct nvgpu_falcon *flcn,
101 struct nvgpu_falcon_queue *queue, void *data, u32 size)
102{
103 int err = 0;
104
105 err = nvgpu_flcn_copy_to_dmem(flcn, queue->position, data, size, 0);
106 if (err != 0) {
107 nvgpu_err(flcn->g, "flcn-%d, queue-%d", flcn->flcn_id,
108 queue->id);
109 nvgpu_err(flcn->g, "dmem queue write failed");
110 goto exit;
111 }
112
113 queue->position += ALIGN(size, QUEUE_ALIGNMENT);
114
115exit:
116 return err;
117}
118
119static int flcn_queue_pop_dmem(struct nvgpu_falcon *flcn,
120 struct nvgpu_falcon_queue *queue, void *data, u32 size,
121 u32 *bytes_read)
122{
123 struct gk20a *g = flcn->g;
124 u32 q_tail = queue->position;
125 u32 q_head = 0;
126 u32 used = 0;
127 int err = 0;
128
129 *bytes_read = 0;
130
131 err = queue->head(flcn, queue, &q_head, QUEUE_GET);
132 if (err != 0) {
133 nvgpu_err(flcn->g, "flcn-%d, queue-%d, head GET failed",
134 flcn->flcn_id, queue->id);
135 goto exit;
136 }
137
138 if (q_head == q_tail) {
139 goto exit;
140 } else if (q_head > q_tail) {
141 used = q_head - q_tail;
142 } else {
143 used = queue->offset + queue->size - q_tail;
144 }
145
146 if (size > used) {
147 nvgpu_warn(g, "queue size smaller than request read");
148 size = used;
149 }
150
151 err = nvgpu_flcn_copy_from_dmem(flcn, q_tail, data, size, 0);
152 if (err != 0) {
153 nvgpu_err(g, "flcn-%d, queue-%d", flcn->flcn_id,
154 queue->id);
155 nvgpu_err(flcn->g, "dmem queue read failed");
156 goto exit;
157 }
158
159 queue->position += ALIGN(size, QUEUE_ALIGNMENT);
160 *bytes_read = size;
161
162exit:
163 return err;
164}
165
166static int flcn_queue_rewind_dmem(struct nvgpu_falcon *flcn,
167 struct nvgpu_falcon_queue *queue)
168{
169 struct gk20a *g = flcn->g;
170 struct pmu_cmd cmd;
171 int err = 0;
172
173 if (queue->oflag == OFLAG_WRITE) {
174 cmd.hdr.unit_id = PMU_UNIT_REWIND;
175 cmd.hdr.size = (u8)PMU_CMD_HDR_SIZE;
176 err = queue->push(flcn, queue, &cmd, cmd.hdr.size);
177 if (err != 0) {
178 nvgpu_err(g, "flcn-%d queue-%d, rewind request failed",
179 flcn->flcn_id, queue->id);
180 goto exit;
181 } else {
182 nvgpu_pmu_dbg(g, "flcn-%d queue-%d, rewinded",
183 flcn->flcn_id, queue->id);
184 }
185 }
186
187 /* update queue position */
188 queue->position = queue->offset;
189
190 if (queue->oflag == OFLAG_READ) {
191 err = queue->tail(flcn, queue, &queue->position,
192 QUEUE_SET);
193 if (err != 0){
194 nvgpu_err(flcn->g, "flcn-%d queue-%d, position SET failed",
195 flcn->flcn_id, queue->id);
196 goto exit;
197 }
198 }
199
200exit:
201 return err;
202}
203
204/* assign DMEM queue type specific ops */
205static void flcn_queue_init_dmem_queue(struct nvgpu_falcon *flcn,
206 struct nvgpu_falcon_queue *queue)
207{
208 queue->head = flcn_queue_head_dmem;
209 queue->tail = flcn_queue_tail_dmem;
210 queue->has_room = flcn_queue_has_room_dmem;
211 queue->push = flcn_queue_push_dmem;
212 queue->pop = flcn_queue_pop_dmem;
213 queue->rewind = flcn_queue_rewind_dmem;
214}
215
216static int flcn_queue_prepare_write(struct nvgpu_falcon *flcn,
217 struct nvgpu_falcon_queue *queue, u32 size)
218{
219 bool q_rewind = false;
220 int err = 0;
221
222 /* make sure there's enough free space for the write */
223 if (!queue->has_room(flcn, queue, size, &q_rewind)) {
224 nvgpu_pmu_dbg(flcn->g, "queue full: queue-id %d: index %d",
225 queue->id, queue->index);
226 err = -EAGAIN;
227 goto exit;
228 }
229
230 err = queue->head(flcn, queue, &queue->position, QUEUE_GET);
231 if (err != 0) {
232 nvgpu_err(flcn->g, "flcn-%d queue-%d, position GET failed",
233 flcn->flcn_id, queue->id);
234 goto exit;
235 }
236
237 if (q_rewind) {
238 err = queue->rewind(flcn, queue);
239 }
240
241exit:
242 return err;
243}
244
245/* queue public functions */
246
247/* queue push operation with lock */
248int nvgpu_flcn_queue_push(struct nvgpu_falcon *flcn,
249 struct nvgpu_falcon_queue *queue, void *data, u32 size)
250{
251 int err = 0;
252
253 if (queue->oflag != OFLAG_WRITE) {
254 nvgpu_err(flcn->g, "flcn-%d, queue-%d not opened for write",
255 flcn->flcn_id, queue->id);
256 err = -EINVAL;
257 goto exit;
258 }
259
260 /* acquire mutex */
261 nvgpu_mutex_acquire(&queue->mutex);
262
263 err = flcn_queue_prepare_write(flcn, queue, size);
264 if (err != 0) {
265 nvgpu_err(flcn->g, "flcn-%d queue-%d, fail to open",
266 flcn->flcn_id, queue->id);
267 goto unlock_mutex;
268 }
269
270 err = queue->push(flcn, queue, data, size);
271 if (err != 0) {
272 nvgpu_err(flcn->g, "flcn-%d queue-%d, fail to write",
273 flcn->flcn_id, queue->id);
274 }
275
276 err = queue->head(flcn, queue, &queue->position, QUEUE_SET);
277 if (err != 0){
278 nvgpu_err(flcn->g, "flcn-%d queue-%d, position SET failed",
279 flcn->flcn_id, queue->id);
280 }
281
282unlock_mutex:
283 /* release mutex */
284 nvgpu_mutex_release(&queue->mutex);
285exit:
286 return err;
287}
288
289/* queue pop operation with lock */
290int nvgpu_flcn_queue_pop(struct nvgpu_falcon *flcn,
291 struct nvgpu_falcon_queue *queue, void *data, u32 size,
292 u32 *bytes_read)
293{
294 int err = 0;
295
296 if (queue->oflag != OFLAG_READ) {
297 nvgpu_err(flcn->g, "flcn-%d, queue-%d, not opened for read",
298 flcn->flcn_id, queue->id);
299 err = -EINVAL;
300 goto exit;
301 }
302
303 /* acquire mutex */
304 nvgpu_mutex_acquire(&queue->mutex);
305
306 err = queue->tail(flcn, queue, &queue->position, QUEUE_GET);
307 if (err != 0) {
308 nvgpu_err(flcn->g, "flcn-%d queue-%d, position GET failed",
309 flcn->flcn_id, queue->id);
310 goto unlock_mutex;
311 }
312
313 err = queue->pop(flcn, queue, data, size, bytes_read);
314 if (err != 0) {
315 nvgpu_err(flcn->g, "flcn-%d queue-%d, fail to read",
316 flcn->flcn_id, queue->id);
317 }
318
319 err = queue->tail(flcn, queue, &queue->position, QUEUE_SET);
320 if (err != 0){
321 nvgpu_err(flcn->g, "flcn-%d queue-%d, position SET failed",
322 flcn->flcn_id, queue->id);
323 }
324
325unlock_mutex:
326 /* release mutex */
327 nvgpu_mutex_release(&queue->mutex);
328exit:
329 return err;
330}
331
332int nvgpu_flcn_queue_rewind(struct nvgpu_falcon *flcn,
333 struct nvgpu_falcon_queue *queue)
334{
335 int err = 0;
336
337 /* acquire mutex */
338 nvgpu_mutex_acquire(&queue->mutex);
339
340 if (queue->rewind != NULL) {
341 err = queue->rewind(flcn, queue);
342 }
343
344 /* release mutex */
345 nvgpu_mutex_release(&queue->mutex);
346
347 return err;
348}
349
350/* queue is_empty check with lock */
351bool nvgpu_flcn_queue_is_empty(struct nvgpu_falcon *flcn,
352 struct nvgpu_falcon_queue *queue)
353{
354 u32 q_head = 0;
355 u32 q_tail = 0;
356 int err = 0;
357
358 /* acquire mutex */
359 nvgpu_mutex_acquire(&queue->mutex);
360
361 err = queue->head(flcn, queue, &q_head, QUEUE_GET);
362 if (err != 0) {
363 nvgpu_err(flcn->g, "flcn-%d queue-%d, head GET failed",
364 flcn->flcn_id, queue->id);
365 goto exit;
366 }
367
368 err = queue->tail(flcn, queue, &q_tail, QUEUE_GET);
369 if (err != 0) {
370 nvgpu_err(flcn->g, "flcn-%d queue-%d, tail GET failed",
371 flcn->flcn_id, queue->id);
372 goto exit;
373 }
374
375exit:
376 /* release mutex */
377 nvgpu_mutex_release(&queue->mutex);
378
379 return q_head == q_tail;
380}
381
382void nvgpu_flcn_queue_free(struct nvgpu_falcon *flcn,
383 struct nvgpu_falcon_queue *queue)
384{
385 nvgpu_log(flcn->g, gpu_dbg_pmu, "flcn id-%d q-id %d: index %d ",
386 flcn->flcn_id, queue->id, queue->index);
387
388 /* destroy mutex */
389 nvgpu_mutex_destroy(&queue->mutex);
390
391 /* clear data*/
392 memset(queue, 0, sizeof(struct nvgpu_falcon_queue));
393}
394
395int nvgpu_flcn_queue_init(struct nvgpu_falcon *flcn,
396 struct nvgpu_falcon_queue *queue)
397{
398 struct gk20a *g = flcn->g;
399 int err = 0;
400
401 nvgpu_log(g, gpu_dbg_pmu,
402 "flcn id-%d q-id %d: index %d, offset 0x%08x, size 0x%08x",
403 flcn->flcn_id, queue->id, queue->index,
404 queue->offset, queue->size);
405
406 /* init mutex */
407 err = nvgpu_mutex_init(&queue->mutex);
408 if (err != 0) {
409 goto exit;
410 }
411
412 flcn_queue_init_dmem_queue(flcn, queue);
413
414exit:
415 if (err != 0) {
416 nvgpu_err(flcn->g, "flcn-%d queue-%d, init failed",
417 flcn->flcn_id, queue->id);
418 }
419
420 return err;
421}
422
diff --git a/drivers/gpu/nvgpu/common/pmu/pmu.c b/drivers/gpu/nvgpu/common/pmu/pmu.c
index b9ac50be..327f67d3 100644
--- a/drivers/gpu/nvgpu/common/pmu/pmu.c
+++ b/drivers/gpu/nvgpu/common/pmu/pmu.c
@@ -517,8 +517,9 @@ int nvgpu_pmu_destroy(struct gk20a *g)
517 pmu->isr_enabled = false; 517 pmu->isr_enabled = false;
518 nvgpu_mutex_release(&pmu->isr_mutex); 518 nvgpu_mutex_release(&pmu->isr_mutex);
519 519
520 for (i = 0; i < PMU_QUEUE_COUNT; i++) 520 for (i = 0; i < PMU_QUEUE_COUNT; i++) {
521 nvgpu_mutex_destroy(&pmu->queue[i].mutex); 521 nvgpu_flcn_queue_free(pmu->flcn, &pmu->queue[i]);
522 }
522 523
523 nvgpu_pmu_state_change(g, PMU_STATE_OFF, false); 524 nvgpu_pmu_state_change(g, PMU_STATE_OFF, false);
524 pmu->pmu_ready = false; 525 pmu->pmu_ready = false;
diff --git a/drivers/gpu/nvgpu/common/pmu/pmu_fw.c b/drivers/gpu/nvgpu/common/pmu/pmu_fw.c
index 359c19ca..53eae49a 100644
--- a/drivers/gpu/nvgpu/common/pmu/pmu_fw.c
+++ b/drivers/gpu/nvgpu/common/pmu/pmu_fw.c
@@ -848,7 +848,8 @@ static void perfmon_cmd_init_set_mov_avg_v1(struct pmu_perfmon_cmd *pc,
848 init->samples_in_moving_avg = value; 848 init->samples_in_moving_avg = value;
849} 849}
850 850
851static void get_pmu_init_msg_pmu_queue_params_v1(struct pmu_queue *queue, 851static void get_pmu_init_msg_pmu_queue_params_v1(
852 struct nvgpu_falcon_queue *queue,
852 u32 id, void *pmu_init_msg) 853 u32 id, void *pmu_init_msg)
853{ 854{
854 struct pmu_init_msg_pmu_v1 *init = 855 struct pmu_init_msg_pmu_v1 *init =
@@ -859,7 +860,8 @@ static void get_pmu_init_msg_pmu_queue_params_v1(struct pmu_queue *queue,
859 queue->size = init->queue_info[id].size; 860 queue->size = init->queue_info[id].size;
860} 861}
861 862
862static void get_pmu_init_msg_pmu_queue_params_v4(struct pmu_queue *queue, 863static void get_pmu_init_msg_pmu_queue_params_v4(
864 struct nvgpu_falcon_queue *queue,
863 u32 id, void *pmu_init_msg) 865 u32 id, void *pmu_init_msg)
864{ 866{
865 struct pmu_init_msg_pmu_v4 *init = pmu_init_msg; 867 struct pmu_init_msg_pmu_v4 *init = pmu_init_msg;
@@ -885,7 +887,8 @@ static void get_pmu_init_msg_pmu_queue_params_v4(struct pmu_queue *queue,
885 queue->offset = init->queue_offset + current_ptr; 887 queue->offset = init->queue_offset + current_ptr;
886} 888}
887 889
888static void get_pmu_init_msg_pmu_queue_params_v5(struct pmu_queue *queue, 890static void get_pmu_init_msg_pmu_queue_params_v5(
891 struct nvgpu_falcon_queue *queue,
889 u32 id, void *pmu_init_msg) 892 u32 id, void *pmu_init_msg)
890{ 893{
891 struct pmu_init_msg_pmu_v5 *init = pmu_init_msg; 894 struct pmu_init_msg_pmu_v5 *init = pmu_init_msg;
@@ -911,7 +914,8 @@ static void get_pmu_init_msg_pmu_queue_params_v5(struct pmu_queue *queue,
911 queue->offset = init->queue_offset + current_ptr; 914 queue->offset = init->queue_offset + current_ptr;
912} 915}
913 916
914static void get_pmu_init_msg_pmu_queue_params_v3(struct pmu_queue *queue, 917static void get_pmu_init_msg_pmu_queue_params_v3(
918 struct nvgpu_falcon_queue *queue,
915 u32 id, void *pmu_init_msg) 919 u32 id, void *pmu_init_msg)
916{ 920{
917 struct pmu_init_msg_pmu_v3 *init = 921 struct pmu_init_msg_pmu_v3 *init =
diff --git a/drivers/gpu/nvgpu/common/pmu/pmu_ipc.c b/drivers/gpu/nvgpu/common/pmu/pmu_ipc.c
index a00c2a5e..f34e942d 100644
--- a/drivers/gpu/nvgpu/common/pmu/pmu_ipc.c
+++ b/drivers/gpu/nvgpu/common/pmu/pmu_ipc.c
@@ -26,6 +26,7 @@
26#include <nvgpu/timers.h> 26#include <nvgpu/timers.h>
27#include <nvgpu/bug.h> 27#include <nvgpu/bug.h>
28#include <nvgpu/pmuif/nvgpu_gpmu_cmdif.h> 28#include <nvgpu/pmuif/nvgpu_gpmu_cmdif.h>
29#include <nvgpu/falcon.h>
29 30
30#include "gk20a/gk20a.h" 31#include "gk20a/gk20a.h"
31 32
@@ -100,295 +101,56 @@ int nvgpu_pmu_mutex_release(struct nvgpu_pmu *pmu, u32 id, u32 *token)
100 return g->ops.pmu.pmu_mutex_release(pmu, id, token); 101 return g->ops.pmu.pmu_mutex_release(pmu, id, token);
101} 102}
102 103
103/* queue */ 104/* PMU falcon queue init */
104int nvgpu_pmu_queue_init(struct nvgpu_pmu *pmu, 105int nvgpu_pmu_queue_init(struct nvgpu_pmu *pmu,
105 u32 id, union pmu_init_msg_pmu *init) 106 u32 id, union pmu_init_msg_pmu *init)
106{ 107{
107 struct gk20a *g = gk20a_from_pmu(pmu); 108 struct gk20a *g = gk20a_from_pmu(pmu);
108 struct pmu_queue *queue = &pmu->queue[id]; 109 struct nvgpu_falcon_queue *queue = NULL;
109 int err; 110 u32 oflag = 0;
110 111 int err = 0;
111 err = nvgpu_mutex_init(&queue->mutex);
112 if (err)
113 return err;
114
115 queue->id = id;
116 g->ops.pmu_ver.get_pmu_init_msg_pmu_queue_params(queue, id, init);
117 queue->mutex_id = id;
118
119 nvgpu_pmu_dbg(g, "queue %d: index %d, offset 0x%08x, size 0x%08x",
120 id, queue->index, queue->offset, queue->size);
121
122 return 0;
123}
124
125static int pmu_queue_head(struct nvgpu_pmu *pmu, struct pmu_queue *queue,
126 u32 *head, bool set)
127{
128 struct gk20a *g = gk20a_from_pmu(pmu);
129
130 return g->ops.pmu.pmu_queue_head(pmu, queue, head, set);
131}
132
133static int pmu_queue_tail(struct nvgpu_pmu *pmu, struct pmu_queue *queue,
134 u32 *tail, bool set)
135{
136 struct gk20a *g = gk20a_from_pmu(pmu);
137
138 return g->ops.pmu.pmu_queue_tail(pmu, queue, tail, set);
139}
140
141static inline void pmu_queue_read(struct nvgpu_pmu *pmu,
142 u32 offset, u8 *dst, u32 size)
143{
144 nvgpu_flcn_copy_from_dmem(pmu->flcn, offset, dst, size, 0);
145}
146
147static inline void pmu_queue_write(struct nvgpu_pmu *pmu,
148 u32 offset, u8 *src, u32 size)
149{
150 nvgpu_flcn_copy_to_dmem(pmu->flcn, offset, src, size, 0);
151}
152
153
154static int pmu_queue_lock(struct nvgpu_pmu *pmu,
155 struct pmu_queue *queue)
156{
157 int err;
158
159 if (PMU_IS_MESSAGE_QUEUE(queue->id))
160 return 0;
161 112
162 if (PMU_IS_SW_COMMAND_QUEUE(queue->id)) { 113 if (PMU_IS_COMMAND_QUEUE(id)) {
163 nvgpu_mutex_acquire(&queue->mutex); 114 /*
164 return 0; 115 * set OFLAG_WRITE for command queue
116 * i.e, push from nvgpu &
117 * pop form falcon ucode
118 */
119 oflag = OFLAG_WRITE;
120 } else if (PMU_IS_MESSAGE_QUEUE(id)) {
121 /*
122 * set OFLAG_READ for message queue
123 * i.e, push from falcon ucode &
124 * pop form nvgpu
125 */
126 oflag = OFLAG_READ;
127 } else {
128 nvgpu_err(g, "invalid queue-id %d", id);
129 err = -EINVAL;
130 goto exit;
165 } 131 }
166 132
167 err = nvgpu_pmu_mutex_acquire(pmu, queue->mutex_id, &queue->mutex_lock); 133 /* init queue parameters */
168 return err; 134 queue = &pmu->queue[id];
169} 135 queue->id = id;
170 136 queue->oflag = oflag;
171static int pmu_queue_unlock(struct nvgpu_pmu *pmu, 137 g->ops.pmu_ver.get_pmu_init_msg_pmu_queue_params(queue, id, init);
172 struct pmu_queue *queue)
173{
174 int err;
175
176 if (PMU_IS_MESSAGE_QUEUE(queue->id))
177 return 0;
178 138
179 if (PMU_IS_SW_COMMAND_QUEUE(queue->id)) { 139 err = nvgpu_flcn_queue_init(pmu->flcn, queue);
180 nvgpu_mutex_release(&queue->mutex); 140 if (err != 0) {
181 return 0; 141 nvgpu_err(g, "queue-%d init failed", queue->id);
182 } 142 }
183 143
184 err = nvgpu_pmu_mutex_release(pmu, queue->mutex_id, &queue->mutex_lock); 144exit:
185 return err; 145 return err;
186} 146}
187 147
188/* called by pmu_read_message, no lock */
189bool nvgpu_pmu_queue_is_empty(struct nvgpu_pmu *pmu,
190 struct pmu_queue *queue)
191{
192 u32 head, tail;
193
194 pmu_queue_head(pmu, queue, &head, QUEUE_GET);
195 if (queue->opened && queue->oflag == OFLAG_READ)
196 tail = queue->position;
197 else
198 pmu_queue_tail(pmu, queue, &tail, QUEUE_GET);
199
200 return head == tail;
201}
202
203static bool pmu_queue_has_room(struct nvgpu_pmu *pmu,
204 struct pmu_queue *queue, u32 size, bool *need_rewind)
205{
206 u32 head, tail;
207 bool rewind = false;
208 unsigned int free;
209
210 size = ALIGN(size, QUEUE_ALIGNMENT);
211
212 pmu_queue_head(pmu, queue, &head, QUEUE_GET);
213 pmu_queue_tail(pmu, queue, &tail, QUEUE_GET);
214 if (head >= tail) {
215 free = queue->offset + queue->size - head;
216 free -= PMU_CMD_HDR_SIZE;
217
218 if (size > free) {
219 rewind = true;
220 head = queue->offset;
221 }
222 }
223
224 if (head < tail)
225 free = tail - head - 1;
226
227 if (need_rewind)
228 *need_rewind = rewind;
229
230 return size <= free;
231}
232
233static int pmu_queue_push(struct nvgpu_pmu *pmu,
234 struct pmu_queue *queue, void *data, u32 size)
235{
236 struct gk20a *g = pmu->g;
237
238 nvgpu_log_fn(g, " ");
239
240 if (!queue->opened && queue->oflag == OFLAG_WRITE) {
241 nvgpu_err(gk20a_from_pmu(pmu), "queue not opened for write");
242 return -EINVAL;
243 }
244
245 pmu_queue_write(pmu, queue->position, data, size);
246 queue->position += ALIGN(size, QUEUE_ALIGNMENT);
247 return 0;
248}
249
250static int pmu_queue_pop(struct nvgpu_pmu *pmu,
251 struct pmu_queue *queue, void *data, u32 size,
252 u32 *bytes_read)
253{
254 u32 head, tail, used;
255
256 *bytes_read = 0;
257
258 if (!queue->opened && queue->oflag == OFLAG_READ) {
259 nvgpu_err(gk20a_from_pmu(pmu), "queue not opened for read");
260 return -EINVAL;
261 }
262
263 pmu_queue_head(pmu, queue, &head, QUEUE_GET);
264 tail = queue->position;
265
266 if (head == tail)
267 return 0;
268
269 if (head > tail)
270 used = head - tail;
271 else
272 used = queue->offset + queue->size - tail;
273
274 if (size > used) {
275 nvgpu_warn(gk20a_from_pmu(pmu),
276 "queue size smaller than request read");
277 size = used;
278 }
279
280 pmu_queue_read(pmu, tail, data, size);
281 queue->position += ALIGN(size, QUEUE_ALIGNMENT);
282 *bytes_read = size;
283 return 0;
284}
285
286static void pmu_queue_rewind(struct nvgpu_pmu *pmu,
287 struct pmu_queue *queue)
288{
289 struct gk20a *g = gk20a_from_pmu(pmu);
290 struct pmu_cmd cmd;
291
292 nvgpu_log_fn(g, " ");
293
294 if (!queue->opened) {
295 nvgpu_err(gk20a_from_pmu(pmu), "queue not opened");
296 return;
297 }
298
299 if (queue->oflag == OFLAG_WRITE) {
300 cmd.hdr.unit_id = PMU_UNIT_REWIND;
301 cmd.hdr.size = PMU_CMD_HDR_SIZE;
302 pmu_queue_push(pmu, queue, &cmd, cmd.hdr.size);
303 nvgpu_pmu_dbg(g, "queue %d rewinded", queue->id);
304 }
305
306 queue->position = queue->offset;
307}
308
309/* open for read and lock the queue */
310static int pmu_queue_open_read(struct nvgpu_pmu *pmu,
311 struct pmu_queue *queue)
312{
313 int err;
314
315 err = pmu_queue_lock(pmu, queue);
316 if (err)
317 return err;
318
319 if (queue->opened)
320 BUG();
321
322 pmu_queue_tail(pmu, queue, &queue->position, QUEUE_GET);
323 queue->oflag = OFLAG_READ;
324 queue->opened = true;
325
326 return 0;
327}
328
329/* open for write and lock the queue
330 * make sure there's enough free space for the write
331 * */
332static int pmu_queue_open_write(struct nvgpu_pmu *pmu,
333 struct pmu_queue *queue, u32 size)
334{
335 struct gk20a *g = gk20a_from_pmu(pmu);
336 bool rewind = false;
337 int err;
338
339 err = pmu_queue_lock(pmu, queue);
340 if (err)
341 return err;
342
343 if (queue->opened)
344 BUG();
345
346 if (!pmu_queue_has_room(pmu, queue, size, &rewind)) {
347 nvgpu_pmu_dbg(g, "queue full: queue-id %d: index %d",
348 queue->id, queue->index);
349 pmu_queue_unlock(pmu, queue);
350 return -EAGAIN;
351 }
352
353 pmu_queue_head(pmu, queue, &queue->position, QUEUE_GET);
354 queue->oflag = OFLAG_WRITE;
355 queue->opened = true;
356
357 if (rewind)
358 pmu_queue_rewind(pmu, queue);
359
360 return 0;
361}
362
363/* close and unlock the queue */
364static int pmu_queue_close(struct nvgpu_pmu *pmu,
365 struct pmu_queue *queue, bool commit)
366{
367 if (!queue->opened)
368 return 0;
369
370 if (commit) {
371 if (queue->oflag == OFLAG_READ)
372 pmu_queue_tail(pmu, queue,
373 &queue->position, QUEUE_SET);
374 else
375 pmu_queue_head(pmu, queue,
376 &queue->position, QUEUE_SET);
377 }
378
379 queue->opened = false;
380
381 pmu_queue_unlock(pmu, queue);
382
383 return 0;
384}
385
386static bool pmu_validate_cmd(struct nvgpu_pmu *pmu, struct pmu_cmd *cmd, 148static bool pmu_validate_cmd(struct nvgpu_pmu *pmu, struct pmu_cmd *cmd,
387 struct pmu_msg *msg, struct pmu_payload *payload, 149 struct pmu_msg *msg, struct pmu_payload *payload,
388 u32 queue_id) 150 u32 queue_id)
389{ 151{
390 struct gk20a *g = gk20a_from_pmu(pmu); 152 struct gk20a *g = gk20a_from_pmu(pmu);
391 struct pmu_queue *queue; 153 struct nvgpu_falcon_queue *queue;
392 u32 in_size, out_size; 154 u32 in_size, out_size;
393 155
394 if (!PMU_IS_SW_COMMAND_QUEUE(queue_id)) 156 if (!PMU_IS_SW_COMMAND_QUEUE(queue_id))
@@ -459,7 +221,7 @@ static int pmu_write_cmd(struct nvgpu_pmu *pmu, struct pmu_cmd *cmd,
459 u32 queue_id, unsigned long timeout_ms) 221 u32 queue_id, unsigned long timeout_ms)
460{ 222{
461 struct gk20a *g = gk20a_from_pmu(pmu); 223 struct gk20a *g = gk20a_from_pmu(pmu);
462 struct pmu_queue *queue; 224 struct nvgpu_falcon_queue *queue;
463 struct nvgpu_timeout timeout; 225 struct nvgpu_timeout timeout;
464 int err; 226 int err;
465 227
@@ -469,7 +231,7 @@ static int pmu_write_cmd(struct nvgpu_pmu *pmu, struct pmu_cmd *cmd,
469 nvgpu_timeout_init(g, &timeout, timeout_ms, NVGPU_TIMER_CPU_TIMER); 231 nvgpu_timeout_init(g, &timeout, timeout_ms, NVGPU_TIMER_CPU_TIMER);
470 232
471 do { 233 do {
472 err = pmu_queue_open_write(pmu, queue, cmd->hdr.size); 234 err = nvgpu_flcn_queue_push(pmu->flcn, queue, cmd, cmd->hdr.size);
473 if (err == -EAGAIN && !nvgpu_timeout_expired(&timeout)) 235 if (err == -EAGAIN && !nvgpu_timeout_expired(&timeout))
474 nvgpu_usleep_range(1000, 2000); 236 nvgpu_usleep_range(1000, 2000);
475 else 237 else
@@ -477,15 +239,6 @@ static int pmu_write_cmd(struct nvgpu_pmu *pmu, struct pmu_cmd *cmd,
477 } while (1); 239 } while (1);
478 240
479 if (err) 241 if (err)
480 goto clean_up;
481
482 pmu_queue_push(pmu, queue, cmd, cmd->hdr.size);
483
484
485 err = pmu_queue_close(pmu, queue, true);
486
487clean_up:
488 if (err)
489 nvgpu_err(g, "fail to write cmd to queue %d", queue_id); 242 nvgpu_err(g, "fail to write cmd to queue %d", queue_id);
490 else 243 else
491 nvgpu_log_fn(g, "done"); 244 nvgpu_log_fn(g, "done");
@@ -840,8 +593,9 @@ static int pmu_handle_event(struct nvgpu_pmu *pmu, struct pmu_msg *msg)
840 return err; 593 return err;
841} 594}
842 595
843static bool pmu_read_message(struct nvgpu_pmu *pmu, struct pmu_queue *queue, 596static bool pmu_read_message(struct nvgpu_pmu *pmu,
844 struct pmu_msg *msg, int *status) 597 struct nvgpu_falcon_queue *queue,
598 struct pmu_msg *msg, int *status)
845{ 599{
846 struct gk20a *g = gk20a_from_pmu(pmu); 600 struct gk20a *g = gk20a_from_pmu(pmu);
847 u32 read_size, bytes_read; 601 u32 read_size, bytes_read;
@@ -849,17 +603,11 @@ static bool pmu_read_message(struct nvgpu_pmu *pmu, struct pmu_queue *queue,
849 603
850 *status = 0; 604 *status = 0;
851 605
852 if (nvgpu_pmu_queue_is_empty(pmu, queue)) 606 if (nvgpu_flcn_queue_is_empty(pmu->flcn, queue)) {
853 return false;
854
855 err = pmu_queue_open_read(pmu, queue);
856 if (err) {
857 nvgpu_err(g, "fail to open queue %d for read", queue->id);
858 *status = err;
859 return false; 607 return false;
860 } 608 }
861 609
862 err = pmu_queue_pop(pmu, queue, &msg->hdr, 610 err = nvgpu_flcn_queue_pop(pmu->flcn, queue, &msg->hdr,
863 PMU_MSG_HDR_SIZE, &bytes_read); 611 PMU_MSG_HDR_SIZE, &bytes_read);
864 if (err || bytes_read != PMU_MSG_HDR_SIZE) { 612 if (err || bytes_read != PMU_MSG_HDR_SIZE) {
865 nvgpu_err(g, "fail to read msg from queue %d", queue->id); 613 nvgpu_err(g, "fail to read msg from queue %d", queue->id);
@@ -868,9 +616,14 @@ static bool pmu_read_message(struct nvgpu_pmu *pmu, struct pmu_queue *queue,
868 } 616 }
869 617
870 if (msg->hdr.unit_id == PMU_UNIT_REWIND) { 618 if (msg->hdr.unit_id == PMU_UNIT_REWIND) {
871 pmu_queue_rewind(pmu, queue); 619 err = nvgpu_flcn_queue_rewind(pmu->flcn, queue);
620 if (err != 0) {
621 nvgpu_err(g, "fail to rewind queue %d", queue->id);
622 *status = err | -EINVAL;
623 goto clean_up;
624 }
872 /* read again after rewind */ 625 /* read again after rewind */
873 err = pmu_queue_pop(pmu, queue, &msg->hdr, 626 err = nvgpu_flcn_queue_pop(pmu->flcn, queue, &msg->hdr,
874 PMU_MSG_HDR_SIZE, &bytes_read); 627 PMU_MSG_HDR_SIZE, &bytes_read);
875 if (err || bytes_read != PMU_MSG_HDR_SIZE) { 628 if (err || bytes_read != PMU_MSG_HDR_SIZE) {
876 nvgpu_err(g, 629 nvgpu_err(g,
@@ -889,7 +642,7 @@ static bool pmu_read_message(struct nvgpu_pmu *pmu, struct pmu_queue *queue,
889 642
890 if (msg->hdr.size > PMU_MSG_HDR_SIZE) { 643 if (msg->hdr.size > PMU_MSG_HDR_SIZE) {
891 read_size = msg->hdr.size - PMU_MSG_HDR_SIZE; 644 read_size = msg->hdr.size - PMU_MSG_HDR_SIZE;
892 err = pmu_queue_pop(pmu, queue, &msg->msg, 645 err = nvgpu_flcn_queue_pop(pmu->flcn, queue, &msg->msg,
893 read_size, &bytes_read); 646 read_size, &bytes_read);
894 if (err || bytes_read != read_size) { 647 if (err || bytes_read != read_size) {
895 nvgpu_err(g, 648 nvgpu_err(g,
@@ -899,19 +652,9 @@ static bool pmu_read_message(struct nvgpu_pmu *pmu, struct pmu_queue *queue,
899 } 652 }
900 } 653 }
901 654
902 err = pmu_queue_close(pmu, queue, true);
903 if (err) {
904 nvgpu_err(g, "fail to close queue %d", queue->id);
905 *status = err;
906 return false;
907 }
908
909 return true; 655 return true;
910 656
911clean_up: 657clean_up:
912 err = pmu_queue_close(pmu, queue, false);
913 if (err)
914 nvgpu_err(g, "fail to close queue %d", queue->id);
915 return false; 658 return false;
916} 659}
917 660
diff --git a/drivers/gpu/nvgpu/gk20a/flcn_gk20a.c b/drivers/gpu/nvgpu/gk20a/flcn_gk20a.c
index 9ca7d91b..c55b90b6 100644
--- a/drivers/gpu/nvgpu/gk20a/flcn_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/flcn_gk20a.c
@@ -649,12 +649,15 @@ void gk20a_falcon_dump_stats(struct nvgpu_falcon *flcn)
649 649
650static void gk20a_falcon_engine_dependency_ops(struct nvgpu_falcon *flcn) 650static void gk20a_falcon_engine_dependency_ops(struct nvgpu_falcon *flcn)
651{ 651{
652 struct gk20a *g = flcn->g;
652 struct nvgpu_falcon_engine_dependency_ops *flcn_eng_dep_ops = 653 struct nvgpu_falcon_engine_dependency_ops *flcn_eng_dep_ops =
653 &flcn->flcn_engine_dep_ops; 654 &flcn->flcn_engine_dep_ops;
654 655
655 switch (flcn->flcn_id) { 656 switch (flcn->flcn_id) {
656 case FALCON_ID_PMU: 657 case FALCON_ID_PMU:
657 flcn_eng_dep_ops->reset_eng = nvgpu_pmu_reset; 658 flcn_eng_dep_ops->reset_eng = nvgpu_pmu_reset;
659 flcn_eng_dep_ops->queue_head = g->ops.pmu.pmu_queue_head;
660 flcn_eng_dep_ops->queue_tail = g->ops.pmu.pmu_queue_tail;
658 break; 661 break;
659 default: 662 default:
660 /* NULL assignment make sure 663 /* NULL assignment make sure
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h
index cfc9128d..6d19d8a3 100644
--- a/drivers/gpu/nvgpu/gk20a/gk20a.h
+++ b/drivers/gpu/nvgpu/gk20a/gk20a.h
@@ -771,7 +771,7 @@ struct gpu_ops {
771 u32 (*pmu_allocation_get_fb_size)( 771 u32 (*pmu_allocation_get_fb_size)(
772 struct nvgpu_pmu *pmu, void *pmu_alloc_ptr); 772 struct nvgpu_pmu *pmu, void *pmu_alloc_ptr);
773 void (*get_pmu_init_msg_pmu_queue_params)( 773 void (*get_pmu_init_msg_pmu_queue_params)(
774 struct pmu_queue *queue, u32 id, 774 struct nvgpu_falcon_queue *queue, u32 id,
775 void *pmu_init_msg); 775 void *pmu_init_msg);
776 void *(*get_pmu_msg_pmu_init_msg_ptr)( 776 void *(*get_pmu_msg_pmu_init_msg_ptr)(
777 struct pmu_init_msg *init); 777 struct pmu_init_msg *init);
@@ -1003,10 +1003,10 @@ struct gpu_ops {
1003 u32 (*pmu_get_queue_head_size)(void); 1003 u32 (*pmu_get_queue_head_size)(void);
1004 u32 (*pmu_get_queue_tail_size)(void); 1004 u32 (*pmu_get_queue_tail_size)(void);
1005 u32 (*pmu_get_queue_tail)(u32 i); 1005 u32 (*pmu_get_queue_tail)(u32 i);
1006 int (*pmu_queue_head)(struct nvgpu_pmu *pmu, 1006 int (*pmu_queue_head)(struct gk20a *g,
1007 struct pmu_queue *queue, u32 *head, bool set); 1007 struct nvgpu_falcon_queue *queue, u32 *head, bool set);
1008 int (*pmu_queue_tail)(struct nvgpu_pmu *pmu, 1008 int (*pmu_queue_tail)(struct gk20a *g,
1009 struct pmu_queue *queue, u32 *tail, bool set); 1009 struct nvgpu_falcon_queue *queue, u32 *tail, bool set);
1010 void (*pmu_msgq_tail)(struct nvgpu_pmu *pmu, 1010 void (*pmu_msgq_tail)(struct nvgpu_pmu *pmu,
1011 u32 *tail, bool set); 1011 u32 *tail, bool set);
1012 u32 (*pmu_mutex_size)(void); 1012 u32 (*pmu_mutex_size)(void);
diff --git a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c
index 11db5b23..bf4673bf 100644
--- a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c
@@ -377,10 +377,9 @@ int gk20a_pmu_mutex_release(struct nvgpu_pmu *pmu, u32 id, u32 *token)
377 return 0; 377 return 0;
378} 378}
379 379
380int gk20a_pmu_queue_head(struct nvgpu_pmu *pmu, struct pmu_queue *queue, 380int gk20a_pmu_queue_head(struct gk20a *g, struct nvgpu_falcon_queue *queue,
381 u32 *head, bool set) 381 u32 *head, bool set)
382{ 382{
383 struct gk20a *g = gk20a_from_pmu(pmu);
384 u32 queue_head_size = 0; 383 u32 queue_head_size = 0;
385 384
386 if (g->ops.pmu.pmu_get_queue_head_size) 385 if (g->ops.pmu.pmu_get_queue_head_size)
@@ -414,10 +413,9 @@ int gk20a_pmu_queue_head(struct nvgpu_pmu *pmu, struct pmu_queue *queue,
414 return 0; 413 return 0;
415} 414}
416 415
417int gk20a_pmu_queue_tail(struct nvgpu_pmu *pmu, struct pmu_queue *queue, 416int gk20a_pmu_queue_tail(struct gk20a *g, struct nvgpu_falcon_queue *queue,
418 u32 *tail, bool set) 417 u32 *tail, bool set)
419{ 418{
420 struct gk20a *g = gk20a_from_pmu(pmu);
421 u32 queue_tail_size = 0; 419 u32 queue_tail_size = 0;
422 420
423 if (g->ops.pmu.pmu_get_queue_tail_size) 421 if (g->ops.pmu.pmu_get_queue_tail_size)
@@ -692,7 +690,7 @@ bool gk20a_pmu_is_interrupted(struct nvgpu_pmu *pmu)
692void gk20a_pmu_isr(struct gk20a *g) 690void gk20a_pmu_isr(struct gk20a *g)
693{ 691{
694 struct nvgpu_pmu *pmu = &g->pmu; 692 struct nvgpu_pmu *pmu = &g->pmu;
695 struct pmu_queue *queue; 693 struct nvgpu_falcon_queue *queue;
696 u32 intr, mask; 694 u32 intr, mask;
697 bool recheck = false; 695 bool recheck = false;
698 696
@@ -749,9 +747,10 @@ void gk20a_pmu_isr(struct gk20a *g)
749 747
750 if (recheck) { 748 if (recheck) {
751 queue = &pmu->queue[PMU_MESSAGE_QUEUE]; 749 queue = &pmu->queue[PMU_MESSAGE_QUEUE];
752 if (!nvgpu_pmu_queue_is_empty(pmu, queue)) 750 if (!nvgpu_flcn_queue_is_empty(pmu->flcn, queue)) {
753 gk20a_writel(g, pwr_falcon_irqsset_r(), 751 gk20a_writel(g, pwr_falcon_irqsset_r(),
754 pwr_falcon_irqsset_swgen0_set_f()); 752 pwr_falcon_irqsset_swgen0_set_f());
753 }
755 } 754 }
756 755
757 nvgpu_mutex_release(&pmu->isr_mutex); 756 nvgpu_mutex_release(&pmu->isr_mutex);
diff --git a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h
index 27d27007..d9c53c28 100644
--- a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h
+++ b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h
@@ -49,9 +49,9 @@ void gk20a_pmu_pg_idle_counter_config(struct gk20a *g, u32 pg_engine_id);
49int gk20a_pmu_mutex_acquire(struct nvgpu_pmu *pmu, u32 id, u32 *token); 49int gk20a_pmu_mutex_acquire(struct nvgpu_pmu *pmu, u32 id, u32 *token);
50int gk20a_pmu_mutex_release(struct nvgpu_pmu *pmu, u32 id, u32 *token); 50int gk20a_pmu_mutex_release(struct nvgpu_pmu *pmu, u32 id, u32 *token);
51 51
52int gk20a_pmu_queue_head(struct nvgpu_pmu *pmu, struct pmu_queue *queue, 52int gk20a_pmu_queue_head(struct gk20a *g, struct nvgpu_falcon_queue *queue,
53 u32 *head, bool set); 53 u32 *head, bool set);
54int gk20a_pmu_queue_tail(struct nvgpu_pmu *pmu, struct pmu_queue *queue, 54int gk20a_pmu_queue_tail(struct gk20a *g, struct nvgpu_falcon_queue *queue,
55 u32 *tail, bool set); 55 u32 *tail, bool set);
56void gk20a_pmu_msgq_tail(struct nvgpu_pmu *pmu, u32 *tail, bool set); 56void gk20a_pmu_msgq_tail(struct nvgpu_pmu *pmu, u32 *tail, bool set);
57 57
diff --git a/drivers/gpu/nvgpu/gp106/flcn_gp106.c b/drivers/gpu/nvgpu/gp106/flcn_gp106.c
index f553f5e1..9f542b6a 100644
--- a/drivers/gpu/nvgpu/gp106/flcn_gp106.c
+++ b/drivers/gpu/nvgpu/gp106/flcn_gp106.c
@@ -28,12 +28,15 @@
28 28
29static void gp106_falcon_engine_dependency_ops(struct nvgpu_falcon *flcn) 29static void gp106_falcon_engine_dependency_ops(struct nvgpu_falcon *flcn)
30{ 30{
31 struct gk20a *g = flcn->g;
31 struct nvgpu_falcon_engine_dependency_ops *flcn_eng_dep_ops = 32 struct nvgpu_falcon_engine_dependency_ops *flcn_eng_dep_ops =
32 &flcn->flcn_engine_dep_ops; 33 &flcn->flcn_engine_dep_ops;
33 34
34 switch (flcn->flcn_id) { 35 switch (flcn->flcn_id) {
35 case FALCON_ID_PMU: 36 case FALCON_ID_PMU:
36 flcn_eng_dep_ops->reset_eng = nvgpu_pmu_reset; 37 flcn_eng_dep_ops->reset_eng = nvgpu_pmu_reset;
38 flcn_eng_dep_ops->queue_head = g->ops.pmu.pmu_queue_head;
39 flcn_eng_dep_ops->queue_tail = g->ops.pmu.pmu_queue_tail;
37 break; 40 break;
38 case FALCON_ID_SEC2: 41 case FALCON_ID_SEC2:
39 flcn_eng_dep_ops->reset_eng = gp106_sec2_reset; 42 flcn_eng_dep_ops->reset_eng = gp106_sec2_reset;
diff --git a/drivers/gpu/nvgpu/include/nvgpu/falcon.h b/drivers/gpu/nvgpu/include/nvgpu/falcon.h
index 6cfb6670..2920e281 100644
--- a/drivers/gpu/nvgpu/include/nvgpu/falcon.h
+++ b/drivers/gpu/nvgpu/include/nvgpu/falcon.h
@@ -167,6 +167,44 @@ struct gk20a;
167struct nvgpu_falcon; 167struct nvgpu_falcon;
168struct nvgpu_falcon_bl_info; 168struct nvgpu_falcon_bl_info;
169 169
170struct nvgpu_falcon_queue {
171
172 /* Queue Type (queue_type) */
173 u8 queue_type;
174
175 /* used by nvgpu, for command LPQ/HPQ */
176 struct nvgpu_mutex mutex;
177
178 /* current write position */
179 u32 position;
180 /* physical dmem offset where this queue begins */
181 u32 offset;
182 /* logical queue identifier */
183 u32 id;
184 /* physical queue index */
185 u32 index;
186 /* in bytes */
187 u32 size;
188 /* open-flag */
189 u32 oflag;
190
191 /* queue type(DMEM-Q/FB-Q) specific ops */
192 int (*rewind)(struct nvgpu_falcon *flcn,
193 struct nvgpu_falcon_queue *queue);
194 int (*pop)(struct nvgpu_falcon *flcn,
195 struct nvgpu_falcon_queue *queue, void *data, u32 size,
196 u32 *bytes_read);
197 int (*push)(struct nvgpu_falcon *flcn,
198 struct nvgpu_falcon_queue *queue, void *data, u32 size);
199 bool (*has_room)(struct nvgpu_falcon *flcn,
200 struct nvgpu_falcon_queue *queue, u32 size,
201 bool *need_rewind);
202 int (*tail)(struct nvgpu_falcon *flcn,
203 struct nvgpu_falcon_queue *queue, u32 *tail, bool set);
204 int (*head)(struct nvgpu_falcon *flcn,
205 struct nvgpu_falcon_queue *queue, u32 *head, bool set);
206};
207
170struct nvgpu_falcon_version_ops { 208struct nvgpu_falcon_version_ops {
171 void (*start_cpu_secure)(struct nvgpu_falcon *flcn); 209 void (*start_cpu_secure)(struct nvgpu_falcon *flcn);
172 void (*write_dmatrfbase)(struct nvgpu_falcon *flcn, u32 addr); 210 void (*write_dmatrfbase)(struct nvgpu_falcon *flcn, u32 addr);
@@ -175,6 +213,11 @@ struct nvgpu_falcon_version_ops {
175/* ops which are falcon engine specific */ 213/* ops which are falcon engine specific */
176struct nvgpu_falcon_engine_dependency_ops { 214struct nvgpu_falcon_engine_dependency_ops {
177 int (*reset_eng)(struct gk20a *g); 215 int (*reset_eng)(struct gk20a *g);
216 int (*queue_head)(struct gk20a *g, struct nvgpu_falcon_queue *queue,
217 u32 *head, bool set);
218 int (*queue_tail)(struct gk20a *g, struct nvgpu_falcon_queue *queue,
219 u32 *tail, bool set);
220 void (*msgq_tail)(struct gk20a *g, u32 *tail, bool set);
178}; 221};
179 222
180struct nvgpu_falcon_ops { 223struct nvgpu_falcon_ops {
@@ -259,6 +302,21 @@ void nvgpu_flcn_dump_stats(struct nvgpu_falcon *flcn);
259int nvgpu_flcn_bl_bootstrap(struct nvgpu_falcon *flcn, 302int nvgpu_flcn_bl_bootstrap(struct nvgpu_falcon *flcn,
260 struct nvgpu_falcon_bl_info *bl_info); 303 struct nvgpu_falcon_bl_info *bl_info);
261 304
305/* queue public functions */
306int nvgpu_flcn_queue_init(struct nvgpu_falcon *flcn,
307 struct nvgpu_falcon_queue *queue);
308bool nvgpu_flcn_queue_is_empty(struct nvgpu_falcon *flcn,
309 struct nvgpu_falcon_queue *queue);
310int nvgpu_flcn_queue_rewind(struct nvgpu_falcon *flcn,
311 struct nvgpu_falcon_queue *queue);
312int nvgpu_flcn_queue_pop(struct nvgpu_falcon *flcn,
313 struct nvgpu_falcon_queue *queue, void *data, u32 size,
314 u32 *bytes_read);
315int nvgpu_flcn_queue_push(struct nvgpu_falcon *flcn,
316 struct nvgpu_falcon_queue *queue, void *data, u32 size);
317void nvgpu_flcn_queue_free(struct nvgpu_falcon *flcn,
318 struct nvgpu_falcon_queue *queue);
319
262void nvgpu_flcn_sw_init(struct gk20a *g, u32 flcn_id); 320void nvgpu_flcn_sw_init(struct gk20a *g, u32 flcn_id);
263 321
264#endif /* __FALCON_H__ */ 322#endif /* __FALCON_H__ */
diff --git a/drivers/gpu/nvgpu/include/nvgpu/pmu.h b/drivers/gpu/nvgpu/include/nvgpu/pmu.h
index 507b8133..4d1bf75a 100644
--- a/drivers/gpu/nvgpu/include/nvgpu/pmu.h
+++ b/drivers/gpu/nvgpu/include/nvgpu/pmu.h
@@ -32,6 +32,7 @@
32#include <nvgpu/nvgpu_common.h> 32#include <nvgpu/nvgpu_common.h>
33#include <nvgpu/flcnif_cmn.h> 33#include <nvgpu/flcnif_cmn.h>
34#include <nvgpu/pmuif/nvgpu_gpmu_cmdif.h> 34#include <nvgpu/pmuif/nvgpu_gpmu_cmdif.h>
35#include <nvgpu/falcon.h>
35 36
36#define nvgpu_pmu_dbg(g, fmt, args...) \ 37#define nvgpu_pmu_dbg(g, fmt, args...) \
37 nvgpu_log(g, gpu_dbg_pmu, fmt, ##args) 38 nvgpu_log(g, gpu_dbg_pmu, fmt, ##args)
@@ -266,30 +267,6 @@ struct pmu_ucode_desc_v1 {
266 u32 compressed; 267 u32 compressed;
267}; 268};
268 269
269struct pmu_queue {
270
271 /* used by hw, for BIOS/SMI queue */
272 u32 mutex_id;
273 u32 mutex_lock;
274 /* used by sw, for LPQ/HPQ queue */
275 struct nvgpu_mutex mutex;
276
277 /* current write position */
278 u32 position;
279 /* physical dmem offset where this queue begins */
280 u32 offset;
281 /* logical queue identifier */
282 u32 id;
283 /* physical queue index */
284 u32 index;
285 /* in bytes */
286 u32 size;
287
288 /* open-flag */
289 u32 oflag;
290 bool opened; /* opened implies locked */
291};
292
293struct pmu_mutex { 270struct pmu_mutex {
294 u32 id; 271 u32 id;
295 u32 index; 272 u32 index;
@@ -345,7 +322,7 @@ struct nvgpu_pmu {
345 322
346 struct pmu_sha1_gid gid_info; 323 struct pmu_sha1_gid gid_info;
347 324
348 struct pmu_queue queue[PMU_QUEUE_COUNT]; 325 struct nvgpu_falcon_queue queue[PMU_QUEUE_COUNT];
349 326
350 struct pmu_sequence *seq; 327 struct pmu_sequence *seq;
351 unsigned long pmu_seq_tbl[PMU_SEQ_TBL_SIZE]; 328 unsigned long pmu_seq_tbl[PMU_SEQ_TBL_SIZE];
@@ -450,7 +427,6 @@ int nvgpu_pmu_mutex_release(struct nvgpu_pmu *pmu, u32 id, u32 *token);
450 427
451int nvgpu_pmu_queue_init(struct nvgpu_pmu *pmu, u32 id, 428int nvgpu_pmu_queue_init(struct nvgpu_pmu *pmu, u32 id,
452 union pmu_init_msg_pmu *init); 429 union pmu_init_msg_pmu *init);
453bool nvgpu_pmu_queue_is_empty(struct nvgpu_pmu *pmu, struct pmu_queue *queue);
454 430
455/* send a cmd to pmu */ 431/* send a cmd to pmu */
456int nvgpu_pmu_cmd_post(struct gk20a *g, struct pmu_cmd *cmd, 432int nvgpu_pmu_cmd_post(struct gk20a *g, struct pmu_cmd *cmd,
diff --git a/drivers/gpu/nvgpu/include/nvgpu/pmuif/gpmuif_cmn.h b/drivers/gpu/nvgpu/include/nvgpu/pmuif/gpmuif_cmn.h
index 2284289e..68df80b4 100644
--- a/drivers/gpu/nvgpu/include/nvgpu/pmuif/gpmuif_cmn.h
+++ b/drivers/gpu/nvgpu/include/nvgpu/pmuif/gpmuif_cmn.h
@@ -27,15 +27,11 @@
27 * commands to the PMU 27 * commands to the PMU
28 */ 28 */
29/* write by sw, read by pmu, protected by sw mutex lock */ 29/* write by sw, read by pmu, protected by sw mutex lock */
30#define PMU_COMMAND_QUEUE_HPQ 0 30#define PMU_COMMAND_QUEUE_HPQ 0U
31/* write by sw, read by pmu, protected by sw mutex lock */ 31/* write by sw, read by pmu, protected by sw mutex lock */
32#define PMU_COMMAND_QUEUE_LPQ 1 32#define PMU_COMMAND_QUEUE_LPQ 1U
33/* read/write by sw/hw, protected by hw pmu mutex, id = 2 */
34#define PMU_COMMAND_QUEUE_BIOS 2
35/* read/write by sw/hw, protected by hw pmu mutex, id = 3 */
36#define PMU_COMMAND_QUEUE_SMI 3
37/* write by pmu, read by sw, accessed by interrupt handler, no lock */ 33/* write by pmu, read by sw, accessed by interrupt handler, no lock */
38#define PMU_MESSAGE_QUEUE 4 34#define PMU_MESSAGE_QUEUE 4U
39#define PMU_QUEUE_COUNT 5 35#define PMU_QUEUE_COUNT 5
40 36
41#define PMU_IS_COMMAND_QUEUE(id) \ 37#define PMU_IS_COMMAND_QUEUE(id) \
@@ -48,15 +44,13 @@
48#define PMU_IS_MESSAGE_QUEUE(id) \ 44#define PMU_IS_MESSAGE_QUEUE(id) \
49 ((id) == PMU_MESSAGE_QUEUE) 45 ((id) == PMU_MESSAGE_QUEUE)
50 46
51enum { 47#define OFLAG_READ 0U
52 OFLAG_READ = 0, 48#define OFLAG_WRITE 1U
53 OFLAG_WRITE
54};
55 49
56#define QUEUE_SET (true) 50#define QUEUE_SET (true)
57#define QUEUE_GET (false) 51#define QUEUE_GET (false)
58 52
59#define QUEUE_ALIGNMENT (4) 53#define QUEUE_ALIGNMENT (4U)
60 54
61/* An enumeration containing all valid logical mutex identifiers */ 55/* An enumeration containing all valid logical mutex identifiers */
62enum { 56enum {