Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
drivers
gpu
drm
nouveau
nouveau_fence.c
Go to the documentation of this file.
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 <
drm/drmP.h
>
28
29
#include <
linux/ktime.h
>
30
#include <linux/hrtimer.h>
31
32
#include "
nouveau_drm.h
"
33
#include "
nouveau_dma.h
"
34
#include "
nouveau_fence.h
"
35
36
void
37
nouveau_fence_context_del
(
struct
nouveau_fence_chan
*fctx)
38
{
39
struct
nouveau_fence
*fence, *fnext;
40
spin_lock(&fctx->
lock
);
41
list_for_each_entry_safe
(fence, fnext, &fctx->
pending
,
head
) {
42
if
(fence->
work
)
43
fence->
work
(fence->
priv
,
false
);
44
fence->
channel
=
NULL
;
45
list_del
(&fence->
head
);
46
nouveau_fence_unref
(&fence);
47
}
48
spin_unlock(&fctx->
lock
);
49
}
50
51
void
52
nouveau_fence_context_new
(
struct
nouveau_fence_chan
*fctx)
53
{
54
INIT_LIST_HEAD(&fctx->
flip
);
55
INIT_LIST_HEAD(&fctx->
pending
);
56
spin_lock_init
(&fctx->
lock
);
57
}
58
59
static
void
60
nouveau_fence_update(
struct
nouveau_channel
*
chan
)
61
{
62
struct
nouveau_fence_priv
*
priv
= chan->
drm
->fence;
63
struct
nouveau_fence_chan
*fctx = chan->
fence
;
64
struct
nouveau_fence
*fence, *fnext;
65
66
spin_lock(&fctx->
lock
);
67
list_for_each_entry_safe
(fence, fnext, &fctx->
pending
,
head
) {
68
if
(priv->
read
(chan) < fence->
sequence
)
69
break
;
70
71
if
(fence->
work
)
72
fence->
work
(fence->
priv
,
true
);
73
fence->
channel
=
NULL
;
74
list_del
(&fence->
head
);
75
nouveau_fence_unref
(&fence);
76
}
77
spin_unlock(&fctx->
lock
);
78
}
79
80
int
81
nouveau_fence_emit
(
struct
nouveau_fence
*fence,
struct
nouveau_channel
*chan)
82
{
83
struct
nouveau_fence_priv
*priv = chan->
drm
->fence;
84
struct
nouveau_fence_chan
*fctx = chan->
fence
;
85
int
ret
;
86
87
fence->
channel
= chan;
88
fence->
timeout
=
jiffies
+ (3 *
DRM_HZ
);
89
fence->
sequence
= ++fctx->
sequence
;
90
91
ret = priv->
emit
(fence);
92
if
(!ret) {
93
kref_get(&fence->
kref
);
94
spin_lock(&fctx->
lock
);
95
list_add_tail
(&fence->
head
, &fctx->
pending
);
96
spin_unlock(&fctx->
lock
);
97
}
98
99
return
ret
;
100
}
101
102
bool
103
nouveau_fence_done
(
struct
nouveau_fence
*fence)
104
{
105
if
(fence->
channel
)
106
nouveau_fence_update(fence->
channel
);
107
return
!fence->
channel
;
108
}
109
110
int
111
nouveau_fence_wait
(
struct
nouveau_fence
*fence,
bool
lazy,
bool
intr
)
112
{
113
unsigned
long
sleep_time =
NSEC_PER_MSEC
/ 1000;
114
ktime_t
t
;
115
int
ret
= 0;
116
117
while
(!
nouveau_fence_done
(fence)) {
118
if
(fence->
timeout
&&
time_after_eq
(
jiffies
, fence->
timeout
)) {
119
ret = -
EBUSY
;
120
break
;
121
}
122
123
__set_current_state
(intr ?
TASK_INTERRUPTIBLE
:
124
TASK_UNINTERRUPTIBLE
);
125
if
(lazy) {
126
t = ktime_set(0, sleep_time);
127
schedule_hrtimeout
(&t,
HRTIMER_MODE_REL
);
128
sleep_time *= 2;
129
if
(sleep_time >
NSEC_PER_MSEC
)
130
sleep_time =
NSEC_PER_MSEC
;
131
}
132
133
if
(intr && signal_pending(
current
)) {
134
ret = -
ERESTARTSYS
;
135
break
;
136
}
137
}
138
139
__set_current_state
(
TASK_RUNNING
);
140
return
ret
;
141
}
142
143
int
144
nouveau_fence_sync
(
struct
nouveau_fence
*fence,
struct
nouveau_channel
*chan)
145
{
146
struct
nouveau_fence_priv
*priv = chan->
drm
->fence;
147
struct
nouveau_channel
*
prev
;
148
int
ret
= 0;
149
150
prev = fence ? fence->
channel
:
NULL
;
151
if
(prev) {
152
if
(
unlikely
(prev != chan && !
nouveau_fence_done
(fence))) {
153
ret = priv->
sync
(fence, prev, chan);
154
if
(
unlikely
(ret))
155
ret =
nouveau_fence_wait
(fence,
true
,
false
);
156
}
157
}
158
159
return
ret
;
160
}
161
162
static
void
163
nouveau_fence_del(
struct
kref
*
kref
)
164
{
165
struct
nouveau_fence
*fence =
container_of
(kref,
typeof
(*fence), kref);
166
kfree
(fence);
167
}
168
169
void
170
nouveau_fence_unref
(
struct
nouveau_fence
**pfence)
171
{
172
if
(*pfence)
173
kref_put(&(*pfence)->kref, nouveau_fence_del);
174
*pfence =
NULL
;
175
}
176
177
struct
nouveau_fence
*
178
nouveau_fence_ref
(
struct
nouveau_fence
*fence)
179
{
180
kref_get(&fence->
kref
);
181
return
fence;
182
}
183
184
int
185
nouveau_fence_new
(
struct
nouveau_channel
*chan,
struct
nouveau_fence
**pfence)
186
{
187
struct
nouveau_fence
*fence;
188
int
ret
= 0;
189
190
if
(
unlikely
(!chan->
fence
))
191
return
-
ENODEV
;
192
193
fence = kzalloc(
sizeof
(*fence),
GFP_KERNEL
);
194
if
(!fence)
195
return
-
ENOMEM
;
196
kref_init(&fence->
kref
);
197
198
if
(chan) {
199
ret =
nouveau_fence_emit
(fence, chan);
200
if
(ret)
201
nouveau_fence_unref
(&fence);
202
}
203
204
*pfence = fence;
205
return
ret
;
206
}
Generated on Thu Jan 10 2013 13:32:48 for Linux Kernel by
1.8.2