2 * Copyright 2012 Red Hat Inc.
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
27 #include <core/client.h>
28 #include <core/gpuobj.h>
29 #include <core/notify.h>
31 #include <nvif/event.h>
32 #include <nvif/unpack.h>
35 nvkm_fifo_pause(struct nvkm_fifo
*fifo
, unsigned long *flags
)
37 return fifo
->func
->pause(fifo
, flags
);
41 nvkm_fifo_start(struct nvkm_fifo
*fifo
, unsigned long *flags
)
43 return fifo
->func
->start(fifo
, flags
);
47 nvkm_fifo_chan_put(struct nvkm_fifo
*fifo
, unsigned long flags
,
48 struct nvkm_fifo_chan
**pchan
)
50 struct nvkm_fifo_chan
*chan
= *pchan
;
53 spin_unlock_irqrestore(&fifo
->lock
, flags
);
57 struct nvkm_fifo_chan
*
58 nvkm_fifo_chan_inst(struct nvkm_fifo
*fifo
, u64 inst
, unsigned long *rflags
)
60 struct nvkm_fifo_chan
*chan
;
62 spin_lock_irqsave(&fifo
->lock
, flags
);
63 list_for_each_entry(chan
, &fifo
->chan
, head
) {
64 if (chan
->inst
->addr
== inst
) {
65 list_del(&chan
->head
);
66 list_add(&chan
->head
, &fifo
->chan
);
71 spin_unlock_irqrestore(&fifo
->lock
, flags
);
75 struct nvkm_fifo_chan
*
76 nvkm_fifo_chan_chid(struct nvkm_fifo
*fifo
, int chid
, unsigned long *rflags
)
78 struct nvkm_fifo_chan
*chan
;
80 spin_lock_irqsave(&fifo
->lock
, flags
);
81 list_for_each_entry(chan
, &fifo
->chan
, head
) {
82 if (chan
->chid
== chid
) {
83 list_del(&chan
->head
);
84 list_add(&chan
->head
, &fifo
->chan
);
89 spin_unlock_irqrestore(&fifo
->lock
, flags
);
94 nvkm_fifo_event_ctor(struct nvkm_object
*object
, void *data
, u32 size
,
95 struct nvkm_notify
*notify
)
106 static const struct nvkm_event_func
107 nvkm_fifo_event_func
= {
108 .ctor
= nvkm_fifo_event_ctor
,
112 nvkm_fifo_uevent_fini(struct nvkm_event
*event
, int type
, int index
)
114 struct nvkm_fifo
*fifo
= container_of(event
, typeof(*fifo
), uevent
);
115 fifo
->func
->uevent_fini(fifo
);
119 nvkm_fifo_uevent_init(struct nvkm_event
*event
, int type
, int index
)
121 struct nvkm_fifo
*fifo
= container_of(event
, typeof(*fifo
), uevent
);
122 fifo
->func
->uevent_init(fifo
);
126 nvkm_fifo_uevent_ctor(struct nvkm_object
*object
, void *data
, u32 size
,
127 struct nvkm_notify
*notify
)
130 struct nvif_notify_uevent_req none
;
134 if (nvif_unvers(req
->none
)) {
135 notify
->size
= sizeof(struct nvif_notify_uevent_rep
);
143 static const struct nvkm_event_func
144 nvkm_fifo_uevent_func
= {
145 .ctor
= nvkm_fifo_uevent_ctor
,
146 .init
= nvkm_fifo_uevent_init
,
147 .fini
= nvkm_fifo_uevent_fini
,
151 nvkm_fifo_uevent(struct nvkm_fifo
*fifo
)
153 struct nvif_notify_uevent_rep rep
= {
155 nvkm_event_send(&fifo
->uevent
, 1, 0, &rep
, sizeof(rep
));
159 nvkm_fifo_class_new(struct nvkm_device
*device
,
160 const struct nvkm_oclass
*oclass
, void *data
, u32 size
,
161 struct nvkm_object
**pobject
)
163 const struct nvkm_fifo_chan_oclass
*sclass
= oclass
->engn
;
164 struct nvkm_fifo
*fifo
= nvkm_fifo(oclass
->engine
);
165 return sclass
->ctor(fifo
, oclass
, data
, size
, pobject
);
168 static const struct nvkm_device_oclass
170 .ctor
= nvkm_fifo_class_new
,
174 nvkm_fifo_class_get(struct nvkm_oclass
*oclass
, int index
,
175 const struct nvkm_device_oclass
**class)
177 struct nvkm_fifo
*fifo
= nvkm_fifo(oclass
->engine
);
178 const struct nvkm_fifo_chan_oclass
*sclass
;
181 while ((sclass
= fifo
->func
->chan
[c
])) {
183 oclass
->base
= sclass
->base
;
184 oclass
->engn
= sclass
;
185 *class = &nvkm_fifo_class
;
194 nvkm_fifo_intr(struct nvkm_engine
*engine
)
196 struct nvkm_fifo
*fifo
= nvkm_fifo(engine
);
197 fifo
->func
->intr(fifo
);
201 nvkm_fifo_fini(struct nvkm_engine
*engine
, bool suspend
)
203 struct nvkm_fifo
*fifo
= nvkm_fifo(engine
);
204 if (fifo
->func
->fini
)
205 fifo
->func
->fini(fifo
);
210 nvkm_fifo_oneinit(struct nvkm_engine
*engine
)
212 struct nvkm_fifo
*fifo
= nvkm_fifo(engine
);
213 if (fifo
->func
->oneinit
)
214 return fifo
->func
->oneinit(fifo
);
219 nvkm_fifo_init(struct nvkm_engine
*engine
)
221 struct nvkm_fifo
*fifo
= nvkm_fifo(engine
);
222 fifo
->func
->init(fifo
);
227 nvkm_fifo_dtor(struct nvkm_engine
*engine
)
229 struct nvkm_fifo
*fifo
= nvkm_fifo(engine
);
231 if (fifo
->func
->dtor
)
232 data
= fifo
->func
->dtor(fifo
);
233 nvkm_event_fini(&fifo
->cevent
);
234 nvkm_event_fini(&fifo
->uevent
);
238 static const struct nvkm_engine_func
240 .dtor
= nvkm_fifo_dtor
,
241 .oneinit
= nvkm_fifo_oneinit
,
242 .init
= nvkm_fifo_init
,
243 .fini
= nvkm_fifo_fini
,
244 .intr
= nvkm_fifo_intr
,
245 .base
.sclass
= nvkm_fifo_class_get
,
249 nvkm_fifo_ctor(const struct nvkm_fifo_func
*func
, struct nvkm_device
*device
,
250 int index
, int nr
, struct nvkm_fifo
*fifo
)
255 INIT_LIST_HEAD(&fifo
->chan
);
256 spin_lock_init(&fifo
->lock
);
258 if (WARN_ON(fifo
->nr
> NVKM_FIFO_CHID_NR
))
259 fifo
->nr
= NVKM_FIFO_CHID_NR
;
262 bitmap_clear(fifo
->mask
, 0, fifo
->nr
);
264 ret
= nvkm_engine_ctor(&nvkm_fifo
, device
, index
, 0x00000100,
265 true, &fifo
->engine
);
269 if (func
->uevent_init
) {
270 ret
= nvkm_event_init(&nvkm_fifo_uevent_func
, 1, 1,
276 return nvkm_event_init(&nvkm_fifo_event_func
, 1, 1, &fifo
->cevent
);