Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux...
[pandora-kernel.git] / drivers / gpu / drm / nouveau / nouveau_channel.c
1 /*
2  * Copyright 2005-2006 Stephane Marchesin
3  * All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the next
13  * paragraph) shall be included in all copies or substantial portions of the
14  * Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  */
24
25 #include "drmP.h"
26 #include "drm.h"
27 #include "nouveau_drv.h"
28 #include "nouveau_drm.h"
29 #include "nouveau_dma.h"
30
31 static int
32 nouveau_channel_pushbuf_ctxdma_init(struct nouveau_channel *chan)
33 {
34         struct drm_device *dev = chan->dev;
35         struct drm_nouveau_private *dev_priv = dev->dev_private;
36         struct nouveau_bo *pb = chan->pushbuf_bo;
37         struct nouveau_gpuobj *pushbuf = NULL;
38         int ret;
39
40         if (dev_priv->card_type >= NV_50) {
41                 if (dev_priv->card_type < NV_C0) {
42                         ret = nouveau_gpuobj_dma_new(chan,
43                                                      NV_CLASS_DMA_IN_MEMORY, 0,
44                                                      (1ULL << 40),
45                                                      NV_MEM_ACCESS_RO,
46                                                      NV_MEM_TARGET_VM,
47                                                      &pushbuf);
48                 }
49                 chan->pushbuf_base = pb->bo.offset;
50         } else
51         if (pb->bo.mem.mem_type == TTM_PL_TT) {
52                 ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, 0,
53                                              dev_priv->gart_info.aper_size,
54                                              NV_MEM_ACCESS_RO,
55                                              NV_MEM_TARGET_GART, &pushbuf);
56                 chan->pushbuf_base = pb->bo.mem.start << PAGE_SHIFT;
57         } else
58         if (dev_priv->card_type != NV_04) {
59                 ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, 0,
60                                              dev_priv->fb_available_size,
61                                              NV_MEM_ACCESS_RO,
62                                              NV_MEM_TARGET_VRAM, &pushbuf);
63                 chan->pushbuf_base = pb->bo.mem.start << PAGE_SHIFT;
64         } else {
65                 /* NV04 cmdbuf hack, from original ddx.. not sure of it's
66                  * exact reason for existing :)  PCI access to cmdbuf in
67                  * VRAM.
68                  */
69                 ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
70                                              pci_resource_start(dev->pdev, 1),
71                                              dev_priv->fb_available_size,
72                                              NV_MEM_ACCESS_RO,
73                                              NV_MEM_TARGET_PCI, &pushbuf);
74                 chan->pushbuf_base = pb->bo.mem.start << PAGE_SHIFT;
75         }
76
77         nouveau_gpuobj_ref(pushbuf, &chan->pushbuf);
78         nouveau_gpuobj_ref(NULL, &pushbuf);
79         return ret;
80 }
81
82 static struct nouveau_bo *
83 nouveau_channel_user_pushbuf_alloc(struct drm_device *dev)
84 {
85         struct nouveau_bo *pushbuf = NULL;
86         int location, ret;
87
88         if (nouveau_vram_pushbuf)
89                 location = TTM_PL_FLAG_VRAM;
90         else
91                 location = TTM_PL_FLAG_TT;
92
93         ret = nouveau_bo_new(dev, NULL, 65536, 0, location, 0, 0x0000, false,
94                              true, &pushbuf);
95         if (ret) {
96                 NV_ERROR(dev, "error allocating DMA push buffer: %d\n", ret);
97                 return NULL;
98         }
99
100         ret = nouveau_bo_pin(pushbuf, location);
101         if (ret) {
102                 NV_ERROR(dev, "error pinning DMA push buffer: %d\n", ret);
103                 nouveau_bo_ref(NULL, &pushbuf);
104                 return NULL;
105         }
106
107         ret = nouveau_bo_map(pushbuf);
108         if (ret) {
109                 nouveau_bo_unpin(pushbuf);
110                 nouveau_bo_ref(NULL, &pushbuf);
111                 return NULL;
112         }
113
114         return pushbuf;
115 }
116
117 /* allocates and initializes a fifo for user space consumption */
118 int
119 nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret,
120                       struct drm_file *file_priv,
121                       uint32_t vram_handle, uint32_t gart_handle)
122 {
123         struct drm_nouveau_private *dev_priv = dev->dev_private;
124         struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
125         struct nouveau_channel *chan;
126         unsigned long flags;
127         int ret;
128
129         /* allocate and lock channel structure */
130         chan = kzalloc(sizeof(*chan), GFP_KERNEL);
131         if (!chan)
132                 return -ENOMEM;
133         chan->dev = dev;
134         chan->file_priv = file_priv;
135         chan->vram_handle = vram_handle;
136         chan->gart_handle = gart_handle;
137
138         kref_init(&chan->ref);
139         atomic_set(&chan->users, 1);
140         mutex_init(&chan->mutex);
141         mutex_lock(&chan->mutex);
142
143         /* allocate hw channel id */
144         spin_lock_irqsave(&dev_priv->channels.lock, flags);
145         for (chan->id = 0; chan->id < pfifo->channels; chan->id++) {
146                 if (!dev_priv->channels.ptr[chan->id]) {
147                         nouveau_channel_ref(chan, &dev_priv->channels.ptr[chan->id]);
148                         break;
149                 }
150         }
151         spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
152
153         if (chan->id == pfifo->channels) {
154                 mutex_unlock(&chan->mutex);
155                 kfree(chan);
156                 return -ENODEV;
157         }
158
159         NV_DEBUG(dev, "initialising channel %d\n", chan->id);
160         INIT_LIST_HEAD(&chan->nvsw.vbl_wait);
161         INIT_LIST_HEAD(&chan->nvsw.flip);
162         INIT_LIST_HEAD(&chan->fence.pending);
163
164         /* Allocate DMA push buffer */
165         chan->pushbuf_bo = nouveau_channel_user_pushbuf_alloc(dev);
166         if (!chan->pushbuf_bo) {
167                 ret = -ENOMEM;
168                 NV_ERROR(dev, "pushbuf %d\n", ret);
169                 nouveau_channel_put(&chan);
170                 return ret;
171         }
172
173         nouveau_dma_pre_init(chan);
174         chan->user_put = 0x40;
175         chan->user_get = 0x44;
176
177         /* Allocate space for per-channel fixed notifier memory */
178         ret = nouveau_notifier_init_channel(chan);
179         if (ret) {
180                 NV_ERROR(dev, "ntfy %d\n", ret);
181                 nouveau_channel_put(&chan);
182                 return ret;
183         }
184
185         /* Setup channel's default objects */
186         ret = nouveau_gpuobj_channel_init(chan, vram_handle, gart_handle);
187         if (ret) {
188                 NV_ERROR(dev, "gpuobj %d\n", ret);
189                 nouveau_channel_put(&chan);
190                 return ret;
191         }
192
193         /* Create a dma object for the push buffer */
194         ret = nouveau_channel_pushbuf_ctxdma_init(chan);
195         if (ret) {
196                 NV_ERROR(dev, "pbctxdma %d\n", ret);
197                 nouveau_channel_put(&chan);
198                 return ret;
199         }
200
201         /* disable the fifo caches */
202         pfifo->reassign(dev, false);
203
204         /* Construct inital RAMFC for new channel */
205         ret = pfifo->create_context(chan);
206         if (ret) {
207                 nouveau_channel_put(&chan);
208                 return ret;
209         }
210
211         pfifo->reassign(dev, true);
212
213         ret = nouveau_dma_init(chan);
214         if (!ret)
215                 ret = nouveau_fence_channel_init(chan);
216         if (ret) {
217                 nouveau_channel_put(&chan);
218                 return ret;
219         }
220
221         nouveau_debugfs_channel_init(chan);
222
223         NV_DEBUG(dev, "channel %d initialised\n", chan->id);
224         *chan_ret = chan;
225         return 0;
226 }
227
228 struct nouveau_channel *
229 nouveau_channel_get_unlocked(struct nouveau_channel *ref)
230 {
231         struct nouveau_channel *chan = NULL;
232
233         if (likely(ref && atomic_inc_not_zero(&ref->users)))
234                 nouveau_channel_ref(ref, &chan);
235
236         return chan;
237 }
238
239 struct nouveau_channel *
240 nouveau_channel_get(struct drm_device *dev, struct drm_file *file_priv, int id)
241 {
242         struct drm_nouveau_private *dev_priv = dev->dev_private;
243         struct nouveau_channel *chan;
244         unsigned long flags;
245
246         if (unlikely(id < 0 || id >= NOUVEAU_MAX_CHANNEL_NR))
247                 return ERR_PTR(-EINVAL);
248
249         spin_lock_irqsave(&dev_priv->channels.lock, flags);
250         chan = nouveau_channel_get_unlocked(dev_priv->channels.ptr[id]);
251         spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
252
253         if (unlikely(!chan))
254                 return ERR_PTR(-EINVAL);
255
256         if (unlikely(file_priv && chan->file_priv != file_priv)) {
257                 nouveau_channel_put_unlocked(&chan);
258                 return ERR_PTR(-EINVAL);
259         }
260
261         mutex_lock(&chan->mutex);
262         return chan;
263 }
264
265 void
266 nouveau_channel_put_unlocked(struct nouveau_channel **pchan)
267 {
268         struct nouveau_channel *chan = *pchan;
269         struct drm_device *dev = chan->dev;
270         struct drm_nouveau_private *dev_priv = dev->dev_private;
271         struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
272         struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
273         struct nouveau_crypt_engine *pcrypt = &dev_priv->engine.crypt;
274         unsigned long flags;
275
276         /* decrement the refcount, and we're done if there's still refs */
277         if (likely(!atomic_dec_and_test(&chan->users))) {
278                 nouveau_channel_ref(NULL, pchan);
279                 return;
280         }
281
282         /* noone wants the channel anymore */
283         NV_DEBUG(dev, "freeing channel %d\n", chan->id);
284         nouveau_debugfs_channel_fini(chan);
285
286         /* give it chance to idle */
287         nouveau_channel_idle(chan);
288
289         /* ensure all outstanding fences are signaled.  they should be if the
290          * above attempts at idling were OK, but if we failed this'll tell TTM
291          * we're done with the buffers.
292          */
293         nouveau_fence_channel_fini(chan);
294
295         /* boot it off the hardware */
296         pfifo->reassign(dev, false);
297
298         /* We want to give pgraph a chance to idle and get rid of all
299          * potential errors. We need to do this without the context
300          * switch lock held, otherwise the irq handler is unable to
301          * process them.
302          */
303         if (pgraph->channel(dev) == chan)
304                 nouveau_wait_for_idle(dev);
305
306         /* destroy the engine specific contexts */
307         pfifo->destroy_context(chan);
308         pgraph->destroy_context(chan);
309         if (pcrypt->destroy_context)
310                 pcrypt->destroy_context(chan);
311
312         pfifo->reassign(dev, true);
313
314         /* aside from its resources, the channel should now be dead,
315          * remove it from the channel list
316          */
317         spin_lock_irqsave(&dev_priv->channels.lock, flags);
318         nouveau_channel_ref(NULL, &dev_priv->channels.ptr[chan->id]);
319         spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
320
321         /* destroy any resources the channel owned */
322         nouveau_gpuobj_ref(NULL, &chan->pushbuf);
323         if (chan->pushbuf_bo) {
324                 nouveau_bo_unmap(chan->pushbuf_bo);
325                 nouveau_bo_unpin(chan->pushbuf_bo);
326                 nouveau_bo_ref(NULL, &chan->pushbuf_bo);
327         }
328         nouveau_gpuobj_channel_takedown(chan);
329         nouveau_notifier_takedown_channel(chan);
330
331         nouveau_channel_ref(NULL, pchan);
332 }
333
334 void
335 nouveau_channel_put(struct nouveau_channel **pchan)
336 {
337         mutex_unlock(&(*pchan)->mutex);
338         nouveau_channel_put_unlocked(pchan);
339 }
340
341 static void
342 nouveau_channel_del(struct kref *ref)
343 {
344         struct nouveau_channel *chan =
345                 container_of(ref, struct nouveau_channel, ref);
346
347         kfree(chan);
348 }
349
350 void
351 nouveau_channel_ref(struct nouveau_channel *chan,
352                     struct nouveau_channel **pchan)
353 {
354         if (chan)
355                 kref_get(&chan->ref);
356
357         if (*pchan)
358                 kref_put(&(*pchan)->ref, nouveau_channel_del);
359
360         *pchan = chan;
361 }
362
363 void
364 nouveau_channel_idle(struct nouveau_channel *chan)
365 {
366         struct drm_device *dev = chan->dev;
367         struct nouveau_fence *fence = NULL;
368         int ret;
369
370         nouveau_fence_update(chan);
371
372         if (chan->fence.sequence != chan->fence.sequence_ack) {
373                 ret = nouveau_fence_new(chan, &fence, true);
374                 if (!ret) {
375                         ret = nouveau_fence_wait(fence, false, false);
376                         nouveau_fence_unref(&fence);
377                 }
378
379                 if (ret)
380                         NV_ERROR(dev, "Failed to idle channel %d.\n", chan->id);
381         }
382 }
383
384 /* cleans up all the fifos from file_priv */
385 void
386 nouveau_channel_cleanup(struct drm_device *dev, struct drm_file *file_priv)
387 {
388         struct drm_nouveau_private *dev_priv = dev->dev_private;
389         struct nouveau_engine *engine = &dev_priv->engine;
390         struct nouveau_channel *chan;
391         int i;
392
393         NV_DEBUG(dev, "clearing FIFO enables from file_priv\n");
394         for (i = 0; i < engine->fifo.channels; i++) {
395                 chan = nouveau_channel_get(dev, file_priv, i);
396                 if (IS_ERR(chan))
397                         continue;
398
399                 atomic_dec(&chan->users);
400                 nouveau_channel_put(&chan);
401         }
402 }
403
404
405 /***********************************
406  * ioctls wrapping the functions
407  ***********************************/
408
409 static int
410 nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data,
411                          struct drm_file *file_priv)
412 {
413         struct drm_nouveau_private *dev_priv = dev->dev_private;
414         struct drm_nouveau_channel_alloc *init = data;
415         struct nouveau_channel *chan;
416         int ret;
417
418         if (dev_priv->engine.graph.accel_blocked)
419                 return -ENODEV;
420
421         if (init->fb_ctxdma_handle == ~0 || init->tt_ctxdma_handle == ~0)
422                 return -EINVAL;
423
424         ret = nouveau_channel_alloc(dev, &chan, file_priv,
425                                     init->fb_ctxdma_handle,
426                                     init->tt_ctxdma_handle);
427         if (ret)
428                 return ret;
429         init->channel  = chan->id;
430
431         if (chan->dma.ib_max)
432                 init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM |
433                                         NOUVEAU_GEM_DOMAIN_GART;
434         else if (chan->pushbuf_bo->bo.mem.mem_type == TTM_PL_VRAM)
435                 init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM;
436         else
437                 init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_GART;
438
439         if (dev_priv->card_type < NV_C0) {
440                 init->subchan[0].handle = NvM2MF;
441                 if (dev_priv->card_type < NV_50)
442                         init->subchan[0].grclass = 0x0039;
443                 else
444                         init->subchan[0].grclass = 0x5039;
445                 init->subchan[1].handle = NvSw;
446                 init->subchan[1].grclass = NV_SW;
447                 init->nr_subchan = 2;
448         } else {
449                 init->subchan[0].handle  = 0x9039;
450                 init->subchan[0].grclass = 0x9039;
451                 init->nr_subchan = 1;
452         }
453
454         /* Named memory object area */
455         ret = drm_gem_handle_create(file_priv, chan->notifier_bo->gem,
456                                     &init->notifier_handle);
457
458         if (ret == 0)
459                 atomic_inc(&chan->users); /* userspace reference */
460         nouveau_channel_put(&chan);
461         return ret;
462 }
463
464 static int
465 nouveau_ioctl_fifo_free(struct drm_device *dev, void *data,
466                         struct drm_file *file_priv)
467 {
468         struct drm_nouveau_channel_free *req = data;
469         struct nouveau_channel *chan;
470
471         chan = nouveau_channel_get(dev, file_priv, req->channel);
472         if (IS_ERR(chan))
473                 return PTR_ERR(chan);
474
475         atomic_dec(&chan->users);
476         nouveau_channel_put(&chan);
477         return 0;
478 }
479
480 /***********************************
481  * finally, the ioctl table
482  ***********************************/
483
484 struct drm_ioctl_desc nouveau_ioctls[] = {
485         DRM_IOCTL_DEF_DRV(NOUVEAU_GETPARAM, nouveau_ioctl_getparam, DRM_UNLOCKED|DRM_AUTH),
486         DRM_IOCTL_DEF_DRV(NOUVEAU_SETPARAM, nouveau_ioctl_setparam, DRM_UNLOCKED|DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
487         DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_ALLOC, nouveau_ioctl_fifo_alloc, DRM_UNLOCKED|DRM_AUTH),
488         DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_FREE, nouveau_ioctl_fifo_free, DRM_UNLOCKED|DRM_AUTH),
489         DRM_IOCTL_DEF_DRV(NOUVEAU_GROBJ_ALLOC, nouveau_ioctl_grobj_alloc, DRM_UNLOCKED|DRM_AUTH),
490         DRM_IOCTL_DEF_DRV(NOUVEAU_NOTIFIEROBJ_ALLOC, nouveau_ioctl_notifier_alloc, DRM_UNLOCKED|DRM_AUTH),
491         DRM_IOCTL_DEF_DRV(NOUVEAU_GPUOBJ_FREE, nouveau_ioctl_gpuobj_free, DRM_UNLOCKED|DRM_AUTH),
492         DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_NEW, nouveau_gem_ioctl_new, DRM_UNLOCKED|DRM_AUTH),
493         DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_PUSHBUF, nouveau_gem_ioctl_pushbuf, DRM_UNLOCKED|DRM_AUTH),
494         DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_PREP, nouveau_gem_ioctl_cpu_prep, DRM_UNLOCKED|DRM_AUTH),
495         DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_FINI, nouveau_gem_ioctl_cpu_fini, DRM_UNLOCKED|DRM_AUTH),
496         DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_INFO, nouveau_gem_ioctl_info, DRM_UNLOCKED|DRM_AUTH),
497 };
498
499 int nouveau_max_ioctl = DRM_ARRAY_SIZE(nouveau_ioctls);