Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
CodeLinaro
la
kernel
msm-5.4
Commits
24c42013
Commit
24c42013
authored
May 14, 2021
by
qctecmdr
Committed by
Gerrit - the friendly Code Review server
May 14, 2021
Browse files
Merge "msm: kgsl: Fix spinlock recursion issues"
parents
53bb20e6
b6c5beaa
Changes
2
Hide whitespace changes
Inline
Side-by-side
drivers/gpu/msm/kgsl_timeline.c
View file @
24c42013
...
...
@@ -14,8 +14,6 @@
#include "kgsl_timeline.h"
#include "kgsl_trace.h"
static
DEFINE_SPINLOCK
(
fence_lock
);
struct
kgsl_timeline_fence
{
struct
dma_fence
base
;
struct
kgsl_timeline
*
timeline
;
...
...
@@ -152,6 +150,7 @@ static struct kgsl_timeline *kgsl_timeline_alloc(struct kgsl_device_private *dev
trace_kgsl_timeline_alloc
(
id
,
initial
);
spin_lock_init
(
&
timeline
->
lock
);
spin_lock_init
(
&
timeline
->
fence_lock
);
kref_init
(
&
timeline
->
ref
);
...
...
@@ -170,8 +169,7 @@ static void timeline_fence_release(struct dma_fence *fence)
struct
kgsl_timeline_fence
*
cur
,
*
temp
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
timeline
->
lock
,
flags
);
spin_lock
(
&
fence_lock
);
spin_lock_irqsave
(
&
timeline
->
fence_lock
,
flags
);
/* If the fence is still on the active list, remove it */
list_for_each_entry_safe
(
cur
,
temp
,
&
timeline
->
fences
,
node
)
{
...
...
@@ -181,8 +179,7 @@ static void timeline_fence_release(struct dma_fence *fence)
list_del_init
(
&
f
->
node
);
break
;
}
spin_unlock
(
&
fence_lock
);
spin_unlock_irqrestore
(
&
timeline
->
lock
,
flags
);
spin_unlock_irqrestore
(
&
timeline
->
fence_lock
,
flags
);
trace_kgsl_timeline_fence_release
(
f
->
timeline
->
id
,
fence
->
seqno
);
kgsl_timeline_put
(
f
->
timeline
);
...
...
@@ -243,17 +240,17 @@ static void kgsl_timeline_add_fence(struct kgsl_timeline *timeline,
struct
kgsl_timeline_fence
*
entry
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
fence_lock
,
flags
);
spin_lock_irqsave
(
&
timeline
->
fence_lock
,
flags
);
list_for_each_entry
(
entry
,
&
timeline
->
fences
,
node
)
{
if
(
fence
->
base
.
seqno
<
entry
->
base
.
seqno
)
{
list_add_tail
(
&
fence
->
node
,
&
entry
->
node
);
spin_unlock_irqrestore
(
&
fence_lock
,
flags
);
spin_unlock_irqrestore
(
&
timeline
->
fence_lock
,
flags
);
return
;
}
}
list_add_tail
(
&
fence
->
node
,
&
timeline
->
fences
);
spin_unlock_irqrestore
(
&
fence_lock
,
flags
);
spin_unlock_irqrestore
(
&
timeline
->
fence_lock
,
flags
);
}
void
kgsl_timeline_signal
(
struct
kgsl_timeline
*
timeline
,
u64
seqno
)
...
...
@@ -272,22 +269,18 @@ void kgsl_timeline_signal(struct kgsl_timeline *timeline, u64 seqno)
timeline
->
value
=
seqno
;
/* Copy the list out so we can walk it without holding the lock */
spin_lock
(
&
fence_lock
);
list_replace_init
(
&
timeline
->
fences
,
&
temp
);
spin_unlock
(
&
fence_lock
);
list_for_each_entry_safe
(
fence
,
tmp
,
&
temp
,
node
)
{
spin_lock
(
&
timeline
->
fence_lock
);
list_for_each_entry_safe
(
fence
,
tmp
,
&
timeline
->
fences
,
node
)
{
if
(
timeline_fence_signaled
(
&
fence
->
base
))
{
list_del_ini
t
(
&
fence
->
nod
e
);
dma_fence_signal_locked
(
&
fence
->
base
);
dma_fence_ge
t
(
&
fence
->
bas
e
);
list_move
(
&
fence
->
node
,
&
temp
);
}
}
spin_unlock
(
&
timeline
->
fence_lock
);
/* Put the active fences back in the timeline list */
list_for_each_entry_safe
(
fence
,
tmp
,
&
temp
,
node
)
{
list_del_init
(
&
fence
->
nod
e
);
kgsl_timeline_add_fence
(
timeline
,
fenc
e
);
dma_fence_signal_locked
(
&
fence
->
bas
e
);
dma_fence_put
(
&
fence
->
bas
e
);
}
unlock:
...
...
@@ -553,33 +546,19 @@ long kgsl_ioctl_timeline_destroy(struct kgsl_device_private *dev_priv,
INIT_LIST_HEAD
(
&
temp
);
spin_lock_irq
(
&
timeline
->
lock
);
/* Copy any still pending fences to a temporary list */
spin_lock
(
&
fence_lock
);
spin_lock
(
&
timeline
->
fence_lock
);
list_for_each_entry_safe
(
fence
,
tmp
,
&
timeline
->
fences
,
node
)
dma_fence_get
(
&
fence
->
base
);
list_replace_init
(
&
timeline
->
fences
,
&
temp
);
spin_unlock
(
&
fence_lock
);
spin_unlock
(
&
timeline
->
fence_lock
);
/*
* Set an error on each still pending fence and signal
* them to release any callbacks. Hold the refcount
* to avoid fence getting destroyed during signaling.
*/
spin_lock_irq
(
&
timeline
->
lock
);
list_for_each_entry_safe
(
fence
,
tmp
,
&
temp
,
node
)
{
dma_fence_get
(
&
fence
->
base
);
dma_fence_set_error
(
&
fence
->
base
,
-
ENOENT
);
dma_fence_signal_locked
(
&
fence
->
base
);
}
spin_unlock_irq
(
&
timeline
->
lock
);
/*
* Put the fence refcount taken above outside lock
* to avoid spinlock recursion during fence release.
*/
list_for_each_entry_safe
(
fence
,
tmp
,
&
temp
,
node
)
{
list_del_init
(
&
fence
->
node
);
dma_fence_put
(
&
fence
->
base
);
}
spin_unlock_irq
(
&
timeline
->
lock
);
kgsl_timeline_put
(
timeline
);
...
...
drivers/gpu/msm/kgsl_timeline.h
View file @
24c42013
...
...
@@ -16,7 +16,9 @@ struct kgsl_timeline {
int
id
;
/** @value: Current value of the timeline */
u64
value
;
/** @lock: Lock to protect @fences */
/** @fence_lock: Lock to protect @fences */
spinlock_t
fence_lock
;
/** @lock: Lock to use for locking each fence in @fences */
spinlock_t
lock
;
/** @ref: Reference count for the struct */
struct
kref
ref
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment