1 | /* SPDX-License-Identifier: MIT |
2 | * |
3 | * Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved. |
4 | */ |
5 | #include "nouveau_drv.h" |
6 | #include "nouveau_dma.h" |
7 | #include "nouveau_fence.h" |
8 | |
9 | #include "nv50_display.h" |
10 | |
11 | #include <nvif/push906f.h> |
12 | |
13 | #include <nvhw/class/clc36f.h> |
14 | |
15 | static int |
16 | gv100_fence_emit32(struct nouveau_channel *chan, u64 virtual, u32 sequence) |
17 | { |
18 | struct nvif_push *push = &chan->chan.push; |
19 | int ret; |
20 | |
21 | ret = PUSH_WAIT(push, 8); |
22 | if (ret) |
23 | return ret; |
24 | |
25 | PUSH_MTHD(push, NVC36F, SEM_ADDR_LO, lower_32_bits(virtual), |
26 | SEM_ADDR_HI, upper_32_bits(virtual), |
27 | SEM_PAYLOAD_LO, sequence); |
28 | |
29 | PUSH_MTHD(push, NVC36F, SEM_EXECUTE, |
30 | NVDEF(NVC36F, SEM_EXECUTE, OPERATION, RELEASE) | |
31 | NVDEF(NVC36F, SEM_EXECUTE, RELEASE_WFI, EN) | |
32 | NVDEF(NVC36F, SEM_EXECUTE, PAYLOAD_SIZE, 32BIT) | |
33 | NVDEF(NVC36F, SEM_EXECUTE, RELEASE_TIMESTAMP, DIS)); |
34 | |
35 | PUSH_MTHD(push, NVC36F, NON_STALL_INTERRUPT, 0); |
36 | |
37 | PUSH_KICK(push); |
38 | return 0; |
39 | } |
40 | |
41 | static int |
42 | gv100_fence_sync32(struct nouveau_channel *chan, u64 virtual, u32 sequence) |
43 | { |
44 | struct nvif_push *push = &chan->chan.push; |
45 | int ret; |
46 | |
47 | ret = PUSH_WAIT(push, 6); |
48 | if (ret) |
49 | return ret; |
50 | |
51 | PUSH_MTHD(push, NVC36F, SEM_ADDR_LO, lower_32_bits(virtual), |
52 | SEM_ADDR_HI, upper_32_bits(virtual), |
53 | SEM_PAYLOAD_LO, sequence); |
54 | |
55 | PUSH_MTHD(push, NVC36F, SEM_EXECUTE, |
56 | NVDEF(NVC36F, SEM_EXECUTE, OPERATION, ACQ_CIRC_GEQ) | |
57 | NVDEF(NVC36F, SEM_EXECUTE, ACQUIRE_SWITCH_TSG, EN) | |
58 | NVDEF(NVC36F, SEM_EXECUTE, PAYLOAD_SIZE, 32BIT)); |
59 | |
60 | PUSH_KICK(push); |
61 | return 0; |
62 | } |
63 | |
64 | static int |
65 | gv100_fence_context_new(struct nouveau_channel *chan) |
66 | { |
67 | struct nv84_fence_chan *fctx; |
68 | int ret; |
69 | |
70 | ret = nv84_fence_context_new(chan); |
71 | if (ret) |
72 | return ret; |
73 | |
74 | fctx = chan->fence; |
75 | fctx->base.emit32 = gv100_fence_emit32; |
76 | fctx->base.sync32 = gv100_fence_sync32; |
77 | return 0; |
78 | } |
79 | |
80 | int |
81 | gv100_fence_create(struct nouveau_drm *drm) |
82 | { |
83 | struct nv84_fence_priv *priv; |
84 | int ret; |
85 | |
86 | ret = nv84_fence_create(drm); |
87 | if (ret) |
88 | return ret; |
89 | |
90 | priv = drm->fence; |
91 | priv->base.context_new = gv100_fence_context_new; |
92 | return 0; |
93 | } |
94 | |