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.
24 #include <core/object.h>
25 #include <core/client.h>
26 #include <core/device.h>
27 #include <core/class.h>
30 #include <subdev/fb.h>
31 #include <subdev/timer.h>
32 #include <subdev/instmem.h>
34 #include "nouveau_drm.h"
35 #include "nouveau_dma.h"
36 #include "nouveau_gem.h"
37 #include "nouveau_chan.h"
38 #include "nouveau_abi16.h"
40 struct nouveau_abi16
*
41 nouveau_abi16_get(struct drm_file
*file_priv
, struct drm_device
*dev
)
43 struct nouveau_cli
*cli
= nouveau_cli(file_priv
);
44 mutex_lock(&cli
->mutex
);
46 struct nouveau_abi16
*abi16
;
47 cli
->abi16
= abi16
= kzalloc(sizeof(*abi16
), GFP_KERNEL
);
49 INIT_LIST_HEAD(&abi16
->channels
);
50 abi16
->client
= nv_object(cli
);
52 /* allocate device object targeting client's default
53 * device (ie. the one that belongs to the fd it
56 if (nouveau_object_new(abi16
->client
, NVDRM_CLIENT
,
58 &(struct nv_device_class
) {
61 sizeof(struct nv_device_class
),
69 mutex_unlock(&cli
->mutex
);
75 nouveau_abi16_put(struct nouveau_abi16
*abi16
, int ret
)
77 struct nouveau_cli
*cli
= (void *)abi16
->client
;
78 mutex_unlock(&cli
->mutex
);
83 nouveau_abi16_swclass(struct nouveau_drm
*drm
)
85 switch (nv_device(drm
->device
)->card_type
) {
105 nouveau_abi16_ntfy_fini(struct nouveau_abi16_chan
*chan
,
106 struct nouveau_abi16_ntfy
*ntfy
)
108 nouveau_mm_free(&chan
->heap
, &ntfy
->node
);
109 list_del(&ntfy
->head
);
114 nouveau_abi16_chan_fini(struct nouveau_abi16
*abi16
,
115 struct nouveau_abi16_chan
*chan
)
117 struct nouveau_abi16_ntfy
*ntfy
, *temp
;
119 /* cleanup notifier state */
120 list_for_each_entry_safe(ntfy
, temp
, &chan
->notifiers
, head
) {
121 nouveau_abi16_ntfy_fini(chan
, ntfy
);
125 nouveau_bo_vma_del(chan
->ntfy
, &chan
->ntfy_vma
);
126 drm_gem_object_unreference_unlocked(chan
->ntfy
->gem
);
129 if (chan
->heap
.block_size
)
130 nouveau_mm_fini(&chan
->heap
);
132 /* destroy channel object, all children will be killed too */
134 abi16
->handles
&= ~(1 << (chan
->chan
->handle
& 0xffff));
135 nouveau_channel_del(&chan
->chan
);
138 list_del(&chan
->head
);
143 nouveau_abi16_fini(struct nouveau_abi16
*abi16
)
145 struct nouveau_cli
*cli
= (void *)abi16
->client
;
146 struct nouveau_abi16_chan
*chan
, *temp
;
148 /* cleanup channels */
149 list_for_each_entry_safe(chan
, temp
, &abi16
->channels
, head
) {
150 nouveau_abi16_chan_fini(abi16
, chan
);
153 /* destroy the device object */
154 nouveau_object_del(abi16
->client
, NVDRM_CLIENT
, NVDRM_DEVICE
);
161 nouveau_abi16_ioctl_getparam(ABI16_IOCTL_ARGS
)
163 struct nouveau_drm
*drm
= nouveau_drm(dev
);
164 struct nouveau_device
*device
= nv_device(drm
->device
);
165 struct nouveau_timer
*ptimer
= nouveau_timer(device
);
166 struct drm_nouveau_getparam
*getparam
= data
;
168 switch (getparam
->param
) {
169 case NOUVEAU_GETPARAM_CHIPSET_ID
:
170 getparam
->value
= device
->chipset
;
172 case NOUVEAU_GETPARAM_PCI_VENDOR
:
173 getparam
->value
= dev
->pci_vendor
;
175 case NOUVEAU_GETPARAM_PCI_DEVICE
:
176 getparam
->value
= dev
->pci_device
;
178 case NOUVEAU_GETPARAM_BUS_TYPE
:
179 if (drm_pci_device_is_agp(dev
))
182 if (!pci_is_pcie(dev
->pdev
))
187 case NOUVEAU_GETPARAM_FB_SIZE
:
188 getparam
->value
= drm
->gem
.vram_available
;
190 case NOUVEAU_GETPARAM_AGP_SIZE
:
191 getparam
->value
= drm
->gem
.gart_available
;
193 case NOUVEAU_GETPARAM_VM_VRAM_BASE
:
194 getparam
->value
= 0; /* deprecated */
196 case NOUVEAU_GETPARAM_PTIMER_TIME
:
197 getparam
->value
= ptimer
->read(ptimer
);
199 case NOUVEAU_GETPARAM_HAS_BO_USAGE
:
202 case NOUVEAU_GETPARAM_HAS_PAGEFLIP
:
205 case NOUVEAU_GETPARAM_GRAPH_UNITS
:
206 /* NV40 and NV50 versions are quite different, but register
207 * address is the same. User is supposed to know the card
208 * family anyway... */
209 if (device
->chipset
>= 0x40) {
210 getparam
->value
= nv_rd32(device
, 0x001540);
215 nv_debug(device
, "unknown parameter %lld\n", getparam
->param
);
223 nouveau_abi16_ioctl_setparam(ABI16_IOCTL_ARGS
)
229 nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS
)
231 struct drm_nouveau_channel_alloc
*init
= data
;
232 struct nouveau_cli
*cli
= nouveau_cli(file_priv
);
233 struct nouveau_drm
*drm
= nouveau_drm(dev
);
234 struct nouveau_abi16
*abi16
= nouveau_abi16_get(file_priv
, dev
);
235 struct nouveau_abi16_chan
*chan
;
236 struct nouveau_client
*client
;
237 struct nouveau_device
*device
;
238 struct nouveau_instmem
*imem
;
239 struct nouveau_fb
*pfb
;
242 if (unlikely(!abi16
))
244 client
= nv_client(abi16
->client
);
246 if (init
->fb_ctxdma_handle
== ~0 || init
->tt_ctxdma_handle
== ~0)
247 return nouveau_abi16_put(abi16
, -EINVAL
);
249 device
= nv_device(abi16
->device
);
250 imem
= nouveau_instmem(device
);
251 pfb
= nouveau_fb(device
);
253 /* allocate "abi16 channel" data and make up a handle for it */
254 init
->channel
= ffsll(~abi16
->handles
);
255 if (!init
->channel
--)
256 return nouveau_abi16_put(abi16
, -ENOSPC
);
258 chan
= kzalloc(sizeof(*chan
), GFP_KERNEL
);
260 return nouveau_abi16_put(abi16
, -ENOMEM
);
262 INIT_LIST_HEAD(&chan
->notifiers
);
263 list_add(&chan
->head
, &abi16
->channels
);
264 abi16
->handles
|= (1 << init
->channel
);
266 /* create channel object and initialise dma and fence management */
267 if (device
->card_type
>= NV_E0
) {
268 init
->fb_ctxdma_handle
= NVE0_CHANNEL_IND_ENGINE_GR
;
269 init
->tt_ctxdma_handle
= 0;
272 ret
= nouveau_channel_new(drm
, cli
, NVDRM_DEVICE
, NVDRM_CHAN
|
273 init
->channel
, init
->fb_ctxdma_handle
,
274 init
->tt_ctxdma_handle
, &chan
->chan
);
278 if (device
->card_type
>= NV_50
)
279 init
->pushbuf_domains
= NOUVEAU_GEM_DOMAIN_VRAM
|
280 NOUVEAU_GEM_DOMAIN_GART
;
282 if (chan
->chan
->push
.buffer
->bo
.mem
.mem_type
== TTM_PL_VRAM
)
283 init
->pushbuf_domains
= NOUVEAU_GEM_DOMAIN_VRAM
;
285 init
->pushbuf_domains
= NOUVEAU_GEM_DOMAIN_GART
;
287 if (device
->card_type
< NV_C0
) {
288 init
->subchan
[0].handle
= 0x00000000;
289 init
->subchan
[0].grclass
= 0x0000;
290 init
->subchan
[1].handle
= NvSw
;
291 init
->subchan
[1].grclass
= 0x506e;
292 init
->nr_subchan
= 2;
295 /* Named memory object area */
296 ret
= nouveau_gem_new(dev
, PAGE_SIZE
, 0, NOUVEAU_GEM_DOMAIN_GART
,
299 ret
= nouveau_bo_pin(chan
->ntfy
, TTM_PL_FLAG_TT
);
303 if (device
->card_type
>= NV_50
) {
304 ret
= nouveau_bo_vma_add(chan
->ntfy
, client
->vm
,
310 ret
= drm_gem_handle_create(file_priv
, chan
->ntfy
->gem
,
311 &init
->notifier_handle
);
315 ret
= nouveau_mm_init(&chan
->heap
, 0, PAGE_SIZE
, 1);
318 nouveau_abi16_chan_fini(abi16
, chan
);
319 return nouveau_abi16_put(abi16
, ret
);
324 nouveau_abi16_ioctl_channel_free(ABI16_IOCTL_ARGS
)
326 struct drm_nouveau_channel_free
*req
= data
;
327 struct nouveau_abi16
*abi16
= nouveau_abi16_get(file_priv
, dev
);
328 struct nouveau_abi16_chan
*chan
;
331 if (unlikely(!abi16
))
334 list_for_each_entry(chan
, &abi16
->channels
, head
) {
335 if (chan
->chan
->handle
== (NVDRM_CHAN
| req
->channel
)) {
336 nouveau_abi16_chan_fini(abi16
, chan
);
337 return nouveau_abi16_put(abi16
, 0);
341 return nouveau_abi16_put(abi16
, ret
);
345 nouveau_abi16_ioctl_grobj_alloc(ABI16_IOCTL_ARGS
)
347 struct drm_nouveau_grobj_alloc
*init
= data
;
348 struct nouveau_abi16
*abi16
= nouveau_abi16_get(file_priv
, dev
);
349 struct nouveau_drm
*drm
= nouveau_drm(dev
);
350 struct nouveau_object
*object
;
353 if (unlikely(!abi16
))
356 if (init
->handle
== ~0)
357 return nouveau_abi16_put(abi16
, -EINVAL
);
359 /* compatibility with userspace that assumes 506e for all chipsets */
360 if (init
->class == 0x506e) {
361 init
->class = nouveau_abi16_swclass(drm
);
362 if (init
->class == 0x906e)
363 return nouveau_abi16_put(abi16
, 0);
366 ret
= nouveau_object_new(abi16
->client
, NVDRM_CHAN
| init
->channel
,
367 init
->handle
, init
->class, NULL
, 0, &object
);
368 return nouveau_abi16_put(abi16
, ret
);
372 nouveau_abi16_ioctl_notifierobj_alloc(ABI16_IOCTL_ARGS
)
374 struct drm_nouveau_notifierobj_alloc
*info
= data
;
375 struct nouveau_drm
*drm
= nouveau_drm(dev
);
376 struct nouveau_device
*device
= nv_device(drm
->device
);
377 struct nouveau_abi16
*abi16
= nouveau_abi16_get(file_priv
, dev
);
378 struct nouveau_abi16_chan
*chan
, *temp
;
379 struct nouveau_abi16_ntfy
*ntfy
;
380 struct nouveau_object
*object
;
381 struct nv_dma_class args
;
384 if (unlikely(!abi16
))
387 /* completely unnecessary for these chipsets... */
388 if (unlikely(nv_device(abi16
->device
)->card_type
>= NV_C0
))
389 return nouveau_abi16_put(abi16
, -EINVAL
);
391 list_for_each_entry_safe(chan
, temp
, &abi16
->channels
, head
) {
392 if (chan
->chan
->handle
== (NVDRM_CHAN
| info
->channel
))
398 return nouveau_abi16_put(abi16
, -ENOENT
);
400 ntfy
= kzalloc(sizeof(*ntfy
), GFP_KERNEL
);
402 return nouveau_abi16_put(abi16
, -ENOMEM
);
404 list_add(&ntfy
->head
, &chan
->notifiers
);
405 ntfy
->handle
= info
->handle
;
407 ret
= nouveau_mm_head(&chan
->heap
, 1, info
->size
, info
->size
, 1,
412 args
.start
= ntfy
->node
->offset
;
413 args
.limit
= ntfy
->node
->offset
+ ntfy
->node
->length
- 1;
414 if (device
->card_type
>= NV_50
) {
415 args
.flags
= NV_DMA_TARGET_VM
| NV_DMA_ACCESS_VM
;
416 args
.start
+= chan
->ntfy_vma
.offset
;
417 args
.limit
+= chan
->ntfy_vma
.offset
;
419 if (drm
->agp
.stat
== ENABLED
) {
420 args
.flags
= NV_DMA_TARGET_AGP
| NV_DMA_ACCESS_RDWR
;
421 args
.start
+= drm
->agp
.base
+ chan
->ntfy
->bo
.offset
;
422 args
.limit
+= drm
->agp
.base
+ chan
->ntfy
->bo
.offset
;
424 args
.flags
= NV_DMA_TARGET_VM
| NV_DMA_ACCESS_RDWR
;
425 args
.start
+= chan
->ntfy
->bo
.offset
;
426 args
.limit
+= chan
->ntfy
->bo
.offset
;
429 ret
= nouveau_object_new(abi16
->client
, chan
->chan
->handle
,
430 ntfy
->handle
, 0x003d, &args
,
431 sizeof(args
), &object
);
437 nouveau_abi16_ntfy_fini(chan
, ntfy
);
438 return nouveau_abi16_put(abi16
, ret
);
442 nouveau_abi16_ioctl_gpuobj_free(ABI16_IOCTL_ARGS
)
444 struct drm_nouveau_gpuobj_free
*fini
= data
;
445 struct nouveau_abi16
*abi16
= nouveau_abi16_get(file_priv
, dev
);
446 struct nouveau_abi16_chan
*chan
, *temp
;
447 struct nouveau_abi16_ntfy
*ntfy
;
450 if (unlikely(!abi16
))
453 list_for_each_entry_safe(chan
, temp
, &abi16
->channels
, head
) {
454 if (chan
->chan
->handle
== (NVDRM_CHAN
| fini
->channel
))
460 return nouveau_abi16_put(abi16
, -ENOENT
);
462 /* synchronize with the user channel and destroy the gpu object */
463 nouveau_channel_idle(chan
->chan
);
465 ret
= nouveau_object_del(abi16
->client
, chan
->chan
->handle
, fini
->handle
);
467 return nouveau_abi16_put(abi16
, ret
);
469 /* cleanup extra state if this object was a notifier */
470 list_for_each_entry(ntfy
, &chan
->notifiers
, head
) {
471 if (ntfy
->handle
== fini
->handle
) {
472 nouveau_mm_free(&chan
->heap
, &ntfy
->node
);
473 list_del(&ntfy
->head
);
478 return nouveau_abi16_put(abi16
, 0);