OSDN Git Service

drm: Fix for non-coherent DMA PowerPC
[android-x86/external-libdrm.git] / linux-core / nouveau_fence.c
1 /*
2  * Copyright (C) 2007 Ben Skeggs.
3  * All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining
6  * a copy of this software and associated documentation files (the
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sublicense, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * The above copyright notice and this permission notice (including the
14  * next paragraph) shall be included in all copies or substantial
15  * portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20  * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  *
25  */
26
27 #include "drmP.h"
28 #include "drm.h"
29 #include "nouveau_drv.h"
30 #include "nouveau_dma.h"
31
32 static int
33 nouveau_fence_has_irq(struct drm_device *dev, uint32_t class, uint32_t flags)
34 {
35         struct drm_nouveau_private *dev_priv = dev->dev_private;
36
37         DRM_DEBUG("class=%d, flags=0x%08x\n", class, flags);
38
39         /* DRM's channel always uses IRQs to signal fences */
40         if (class == dev_priv->channel.chan->id)
41                 return 1;
42
43         /* Other channels don't use IRQs at all yet */
44         return 0;
45 }
46
47 static int
48 nouveau_fence_emit(struct drm_device *dev, uint32_t class, uint32_t flags,
49                    uint32_t *breadcrumb, uint32_t *native_type)
50 {
51         struct drm_nouveau_private *dev_priv = dev->dev_private;
52         struct nouveau_channel *chan = dev_priv->fifos[class];
53         struct nouveau_drm_channel *dchan = &dev_priv->channel;
54
55         DRM_DEBUG("class=%d, flags=0x%08x\n", class, flags);
56
57         /* We can't emit fences on client channels, update sequence number
58          * and userspace will emit the fence
59          */
60         *breadcrumb  = ++chan->next_sequence;
61         *native_type = DRM_FENCE_TYPE_EXE;
62         if (chan != dchan->chan) {
63                 DRM_DEBUG("user fence 0x%08x\n", *breadcrumb);
64                 return 0;
65         }
66
67         DRM_DEBUG("emit 0x%08x\n", *breadcrumb);
68         BEGIN_RING(NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_SET_REF, 1);
69         OUT_RING  (*breadcrumb);
70         BEGIN_RING(NvSubM2MF, 0x0150, 1);
71         OUT_RING  (0);
72         FIRE_RING ();
73
74         return 0;
75 }
76
77 static void
78 nouveau_fence_poll(struct drm_device *dev, uint32_t class, uint32_t waiting_types)
79 {
80         struct drm_nouveau_private *dev_priv = dev->dev_private;
81         struct drm_fence_class_manager *fc = &dev->fm.fence_class[class];
82         struct nouveau_channel *chan = dev_priv->fifos[class];
83         uint32_t pending_types = 0;
84
85         DRM_DEBUG("class=%d\n", class);
86         DRM_DEBUG("pending: 0x%08x 0x%08x\n", waiting_types, fc->waiting_types);
87
88         if (pending_types) {
89                 uint32_t sequence = NV_READ(chan->ref_cnt);
90
91                 DRM_DEBUG("got 0x%08x\n", sequence);
92                 drm_fence_handler(dev, class, sequence, waiting_types, 0);
93         }
94 }
95
96 void
97 nouveau_fence_handler(struct drm_device *dev, int channel)
98 {
99         struct drm_fence_manager *fm = &dev->fm;
100         struct drm_fence_class_manager *fc = &fm->fence_class[channel];
101
102         DRM_DEBUG("class=%d\n", channel);
103
104         write_lock(&fm->lock);
105         nouveau_fence_poll(dev, channel, fc->waiting_types);
106         write_unlock(&fm->lock);
107 }
108
109 struct drm_fence_driver nouveau_fence_driver = {
110         .num_classes    = 8,
111         .wrap_diff      = (1 << 30),
112         .flush_diff     = (1 << 29),
113         .sequence_mask  = 0xffffffffU,
114         .has_irq        = nouveau_fence_has_irq,
115         .emit           = nouveau_fence_emit,
116         .flush          = NULL,
117         .poll           = nouveau_fence_poll,
118         .needed_flush   = NULL,
119         .wait           = NULL
120 };