1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#define nv04_sw_chan(p) container_of((p), struct nv04_sw_chan, base)
25#include "priv.h"
26#include "chan.h"
27#include "nvsw.h"
28
29#include <nvif/class.h>
30#include <nvif/if0004.h>
31#include <nvif/ioctl.h>
32#include <nvif/unpack.h>
33
34struct nv04_sw_chan {
35 struct nvkm_sw_chan base;
36 atomic_t ref;
37};
38
39
40
41
42
43static int
44nv04_nvsw_mthd_get_ref(struct nvkm_nvsw *nvsw, void *data, u32 size)
45{
46 struct nv04_sw_chan *chan = nv04_sw_chan(nvsw->chan);
47 union {
48 struct nv04_nvsw_get_ref_v0 v0;
49 } *args = data;
50 int ret = -ENOSYS;
51
52 if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
53 args->v0.ref = atomic_read(&chan->ref);
54 }
55
56 return ret;
57}
58
59static int
60nv04_nvsw_mthd(struct nvkm_nvsw *nvsw, u32 mthd, void *data, u32 size)
61{
62 switch (mthd) {
63 case NV04_NVSW_GET_REF:
64 return nv04_nvsw_mthd_get_ref(nvsw, data, size);
65 default:
66 break;
67 }
68 return -EINVAL;
69}
70
71static const struct nvkm_nvsw_func
72nv04_nvsw = {
73 .mthd = nv04_nvsw_mthd,
74};
75
76static int
77nv04_nvsw_new(struct nvkm_sw_chan *chan, const struct nvkm_oclass *oclass,
78 void *data, u32 size, struct nvkm_object **pobject)
79{
80 return nvkm_nvsw_new_(&nv04_nvsw, chan, oclass, data, size, pobject);
81}
82
83
84
85
86
87static bool
88nv04_sw_chan_mthd(struct nvkm_sw_chan *base, int subc, u32 mthd, u32 data)
89{
90 struct nv04_sw_chan *chan = nv04_sw_chan(base);
91
92 switch (mthd) {
93 case 0x0150:
94 atomic_set(&chan->ref, data);
95 return true;
96 default:
97 break;
98 }
99
100 return false;
101}
102
103static const struct nvkm_sw_chan_func
104nv04_sw_chan = {
105 .mthd = nv04_sw_chan_mthd,
106};
107
108static int
109nv04_sw_chan_new(struct nvkm_sw *sw, struct nvkm_fifo_chan *fifo,
110 const struct nvkm_oclass *oclass, struct nvkm_object **pobject)
111{
112 struct nv04_sw_chan *chan;
113
114 if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
115 return -ENOMEM;
116 atomic_set(&chan->ref, 0);
117 *pobject = &chan->base.object;
118
119 return nvkm_sw_chan_ctor(&nv04_sw_chan, sw, fifo, oclass, &chan->base);
120}
121
122
123
124
125
126static const struct nvkm_sw_func
127nv04_sw = {
128 .chan_new = nv04_sw_chan_new,
129 .sclass = {
130 { nv04_nvsw_new, { -1, -1, NVIF_CLASS_SW_NV04 } },
131 {}
132 }
133};
134
135int
136nv04_sw_new(struct nvkm_device *device, int index, struct nvkm_sw **psw)
137{
138 return nvkm_sw_new_(&nv04_sw, device, index, psw);
139}
140