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