Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
b15eb4ea
Commit
b15eb4ea
authored
Jun 04, 2014
by
Dave Airlie
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Revert "drm/radeon: rework page flip handling v3"
This reverts commit
1aab5514
. Apply the fixed up version instead.
parent
5536141d
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
115 additions
and
150 deletions
+115
-150
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon.h
+7
-9
drivers/gpu/drm/radeon/radeon_display.c
drivers/gpu/drm/radeon/radeon_display.c
+106
-139
drivers/gpu/drm/radeon/radeon_mode.h
drivers/gpu/drm/radeon/radeon_mode.h
+2
-2
No files found.
drivers/gpu/drm/radeon/radeon.h
View file @
b15eb4ea
...
@@ -676,16 +676,14 @@ void radeon_doorbell_free(struct radeon_device *rdev, u32 doorbell);
...
@@ -676,16 +676,14 @@ void radeon_doorbell_free(struct radeon_device *rdev, u32 doorbell);
* IRQS.
* IRQS.
*/
*/
struct
radeon_flip_work
{
struct
radeon_unpin_work
{
struct
work_struct
flip_work
;
struct
work_struct
work
;
struct
work_struct
unpin_work
;
struct
radeon_device
*
rdev
;
struct
radeon_device
*
rdev
;
int
crtc_id
;
int
crtc_id
;
struct
drm_framebuffer
*
fb
;
struct
radeon_fence
*
fence
;
struct
drm_pending_vblank_event
*
event
;
struct
drm_pending_vblank_event
*
event
;
struct
radeon_bo
*
old_rbo
;
struct
radeon_bo
*
old_rbo
;
struct
radeon_bo
*
new_rbo
;
u64
new_crtc_base
;
struct
radeon_fence
*
fence
;
};
};
struct
r500_irq_stat_regs
{
struct
r500_irq_stat_regs
{
...
...
drivers/gpu/drm/radeon/radeon_display.c
View file @
b15eb4ea
...
@@ -249,21 +249,16 @@ static void radeon_crtc_destroy(struct drm_crtc *crtc)
...
@@ -249,21 +249,16 @@ static void radeon_crtc_destroy(struct drm_crtc *crtc)
struct
radeon_crtc
*
radeon_crtc
=
to_radeon_crtc
(
crtc
);
struct
radeon_crtc
*
radeon_crtc
=
to_radeon_crtc
(
crtc
);
drm_crtc_cleanup
(
crtc
);
drm_crtc_cleanup
(
crtc
);
destroy_workqueue
(
radeon_crtc
->
flip_queue
);
kfree
(
radeon_crtc
);
kfree
(
radeon_crtc
);
}
}
/**
/*
* radeon_unpin_work_func - unpin old buffer object
* Handle unpin events outside the interrupt handler proper.
*
* @__work - kernel work item
*
* Unpin the old frame buffer object outside of the interrupt handler
*/
*/
static
void
radeon_unpin_work_func
(
struct
work_struct
*
__work
)
static
void
radeon_unpin_work_func
(
struct
work_struct
*
__work
)
{
{
struct
radeon_
flip
_work
*
work
=
struct
radeon_
unpin
_work
*
work
=
container_of
(
__work
,
struct
radeon_
flip_work
,
unpin_
work
);
container_of
(
__work
,
struct
radeon_
unpin_work
,
work
);
int
r
;
int
r
;
/* unpin of the old buffer */
/* unpin of the old buffer */
...
@@ -284,19 +279,30 @@ static void radeon_unpin_work_func(struct work_struct *__work)
...
@@ -284,19 +279,30 @@ static void radeon_unpin_work_func(struct work_struct *__work)
void
radeon_crtc_handle_vblank
(
struct
radeon_device
*
rdev
,
int
crtc_id
)
void
radeon_crtc_handle_vblank
(
struct
radeon_device
*
rdev
,
int
crtc_id
)
{
{
struct
radeon_crtc
*
radeon_crtc
=
rdev
->
mode_info
.
crtcs
[
crtc_id
];
struct
radeon_crtc
*
radeon_crtc
=
rdev
->
mode_info
.
crtcs
[
crtc_id
];
struct
radeon_
flip
_work
*
work
;
struct
radeon_
unpin
_work
*
work
;
unsigned
long
flags
;
unsigned
long
flags
;
u32
update_pending
;
u32
update_pending
;
int
vpos
,
hpos
;
int
vpos
,
hpos
;
spin_lock_irqsave
(
&
rdev
->
ddev
->
event_lock
,
flags
);
spin_lock_irqsave
(
&
rdev
->
ddev
->
event_lock
,
flags
);
work
=
radeon_crtc
->
flip_work
;
work
=
radeon_crtc
->
unpin_work
;
if
(
work
==
NULL
)
{
if
(
work
==
NULL
||
(
work
->
fence
&&
!
radeon_fence_signaled
(
work
->
fence
)))
{
spin_unlock_irqrestore
(
&
rdev
->
ddev
->
event_lock
,
flags
);
spin_unlock_irqrestore
(
&
rdev
->
ddev
->
event_lock
,
flags
);
return
;
return
;
}
}
/* New pageflip, or just completion of a previous one? */
if
(
!
radeon_crtc
->
deferred_flip_completion
)
{
/* do the flip (mmio) */
radeon_page_flip
(
rdev
,
crtc_id
,
work
->
new_crtc_base
);
update_pending
=
radeon_page_flip_pending
(
rdev
,
crtc_id
);
update_pending
=
radeon_page_flip_pending
(
rdev
,
crtc_id
);
}
else
{
/* This is just a completion of a flip queued in crtc
* at last invocation. Make sure we go directly to
* completion routine.
*/
update_pending
=
0
;
}
/* Has the pageflip already completed in crtc, or is it certain
/* Has the pageflip already completed in crtc, or is it certain
* to complete in this vblank?
* to complete in this vblank?
...
@@ -314,9 +320,19 @@ void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id)
...
@@ -314,9 +320,19 @@ void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id)
*/
*/
update_pending
=
0
;
update_pending
=
0
;
}
}
if
(
update_pending
)
{
/* crtc didn't flip in this target vblank interval,
* but flip is pending in crtc. It will complete it
* in next vblank interval, so complete the flip at
* next vblank irq.
*/
radeon_crtc
->
deferred_flip_completion
=
1
;
spin_unlock_irqrestore
(
&
rdev
->
ddev
->
event_lock
,
flags
);
return
;
}
else
{
spin_unlock_irqrestore
(
&
rdev
->
ddev
->
event_lock
,
flags
);
spin_unlock_irqrestore
(
&
rdev
->
ddev
->
event_lock
,
flags
);
if
(
!
update_pending
)
radeon_crtc_handle_flip
(
rdev
,
crtc_id
);
radeon_crtc_handle_flip
(
rdev
,
crtc_id
);
}
}
}
/**
/**
...
@@ -330,7 +346,7 @@ void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id)
...
@@ -330,7 +346,7 @@ void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id)
void
radeon_crtc_handle_flip
(
struct
radeon_device
*
rdev
,
int
crtc_id
)
void
radeon_crtc_handle_flip
(
struct
radeon_device
*
rdev
,
int
crtc_id
)
{
{
struct
radeon_crtc
*
radeon_crtc
=
rdev
->
mode_info
.
crtcs
[
crtc_id
];
struct
radeon_crtc
*
radeon_crtc
=
rdev
->
mode_info
.
crtcs
[
crtc_id
];
struct
radeon_
flip
_work
*
work
;
struct
radeon_
unpin
_work
*
work
;
unsigned
long
flags
;
unsigned
long
flags
;
/* this can happen at init */
/* this can happen at init */
...
@@ -338,14 +354,15 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id)
...
@@ -338,14 +354,15 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id)
return
;
return
;
spin_lock_irqsave
(
&
rdev
->
ddev
->
event_lock
,
flags
);
spin_lock_irqsave
(
&
rdev
->
ddev
->
event_lock
,
flags
);
work
=
radeon_crtc
->
flip
_work
;
work
=
radeon_crtc
->
unpin
_work
;
if
(
work
==
NULL
)
{
if
(
work
==
NULL
)
{
spin_unlock_irqrestore
(
&
rdev
->
ddev
->
event_lock
,
flags
);
spin_unlock_irqrestore
(
&
rdev
->
ddev
->
event_lock
,
flags
);
return
;
return
;
}
}
/* Pageflip completed. Clean up. */
/* Pageflip (will be) certainly completed in this vblank. Clean up. */
radeon_crtc
->
flip_work
=
NULL
;
radeon_crtc
->
unpin_work
=
NULL
;
radeon_crtc
->
deferred_flip_completion
=
0
;
/* wakeup userspace */
/* wakeup userspace */
if
(
work
->
event
)
if
(
work
->
event
)
...
@@ -355,69 +372,83 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id)
...
@@ -355,69 +372,83 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id)
radeon_fence_unref
(
&
work
->
fence
);
radeon_fence_unref
(
&
work
->
fence
);
radeon_irq_kms_pflip_irq_get
(
rdev
,
work
->
crtc_id
);
radeon_irq_kms_pflip_irq_get
(
rdev
,
work
->
crtc_id
);
queue_work
(
radeon_crtc
->
flip_queue
,
&
work
->
unpin_
work
);
schedule_work
(
&
work
->
work
);
}
}
/**
static
int
radeon_crtc_page_flip
(
struct
drm_crtc
*
crtc
,
* radeon_flip_work_func - page flip framebuffer
struct
drm_framebuffer
*
fb
,
*
struct
drm_pending_vblank_event
*
event
,
* @work - kernel work item
uint32_t
page_flip_flags
)
*
* Wait for the buffer object to become idle and do the actual page flip
*/
static
void
radeon_flip_work_func
(
struct
work_struct
*
__work
)
{
{
struct
radeon_flip_work
*
work
=
struct
drm_device
*
dev
=
crtc
->
dev
;
container_of
(
__work
,
struct
radeon_flip_work
,
flip_work
);
struct
radeon_device
*
rdev
=
dev
->
dev_private
;
struct
radeon_device
*
rdev
=
work
->
rdev
;
struct
radeon_crtc
*
radeon_crtc
=
to_radeon_crtc
(
crtc
);
struct
radeon_crtc
*
radeon_crtc
=
rdev
->
mode_info
.
crtcs
[
work
->
crtc_id
];
struct
radeon_framebuffer
*
old_radeon_fb
;
struct
radeon_framebuffer
*
new_radeon_fb
;
struct
drm_gem_object
*
obj
;
struct
radeon_bo
*
rbo
;
struct
radeon_unpin_work
*
work
;
unsigned
long
flags
;
u32
tiling_flags
,
pitch_pixels
;
u64
base
;
int
r
;
struct
drm_crtc
*
crtc
=
&
radeon_crtc
->
base
;
work
=
kzalloc
(
sizeof
*
work
,
GFP_KERNEL
);
struct
drm_framebuffer
*
fb
=
work
->
fb
;
if
(
work
==
NULL
)
return
-
ENOMEM
;
uint32_t
tiling_flags
,
pitch_pixels
;
work
->
event
=
event
;
uint64_t
base
;
work
->
rdev
=
rdev
;
work
->
crtc_id
=
radeon_crtc
->
crtc_id
;
old_radeon_fb
=
to_radeon_framebuffer
(
crtc
->
primary
->
fb
);
new_radeon_fb
=
to_radeon_framebuffer
(
fb
);
/* schedule unpin of the old buffer */
obj
=
old_radeon_fb
->
obj
;
/* take a reference to the old object */
drm_gem_object_reference
(
obj
);
rbo
=
gem_to_radeon_bo
(
obj
);
work
->
old_rbo
=
rbo
;
obj
=
new_radeon_fb
->
obj
;
rbo
=
gem_to_radeon_bo
(
obj
);
unsigned
long
flags
;
spin_lock
(
&
rbo
->
tbo
.
bdev
->
fence_lock
);
int
r
;
if
(
rbo
->
tbo
.
sync_obj
)
work
->
fence
=
radeon_fence_ref
(
rbo
->
tbo
.
sync_obj
);
spin_unlock
(
&
rbo
->
tbo
.
bdev
->
fence_lock
);
down_read
(
&
rdev
->
exclusive_lock
);
INIT_WORK
(
&
work
->
work
,
radeon_unpin_work_func
);
while
(
work
->
fence
)
{
r
=
radeon_fence_wait
(
work
->
fence
,
false
);
if
(
r
==
-
EDEADLK
)
{
up_read
(
&
rdev
->
exclusive_lock
);
r
=
radeon_gpu_reset
(
rdev
);
down_read
(
&
rdev
->
exclusive_lock
);
}
if
(
r
)
{
/* We borrow the event spin lock for protecting unpin_work */
DRM_ERROR
(
"failed to wait on page flip fence (%d)!
\n
"
,
spin_lock_irqsave
(
&
dev
->
event_lock
,
flags
);
r
);
if
(
radeon_crtc
->
unpin_work
)
{
goto
cleanup
;
DRM_DEBUG_DRIVER
(
"flip queue: crtc already busy
\n
"
)
;
}
else
r
=
-
EBUSY
;
radeon_fence_unref
(
&
work
->
fence
)
;
goto
unlock_free
;
}
}
radeon_crtc
->
unpin_work
=
work
;
radeon_crtc
->
deferred_flip_completion
=
0
;
spin_unlock_irqrestore
(
&
dev
->
event_lock
,
flags
);
/* pin the new buffer */
/* pin the new buffer */
DRM_DEBUG_DRIVER
(
"flip-ioctl() cur_fbo = %p, cur_bbo = %p
\n
"
,
DRM_DEBUG_DRIVER
(
"flip-ioctl() cur_fbo = %p, cur_bbo = %p
\n
"
,
work
->
old_rbo
,
work
->
new_
rbo
);
work
->
old_rbo
,
rbo
);
r
=
radeon_bo_reserve
(
work
->
new_
rbo
,
false
);
r
=
radeon_bo_reserve
(
rbo
,
false
);
if
(
unlikely
(
r
!=
0
))
{
if
(
unlikely
(
r
!=
0
))
{
DRM_ERROR
(
"failed to reserve new rbo buffer before flip
\n
"
);
DRM_ERROR
(
"failed to reserve new rbo buffer before flip
\n
"
);
goto
cleanup
;
goto
pflip_
cleanup
;
}
}
/* Only 27 bit offset for legacy CRTC */
/* Only 27 bit offset for legacy CRTC */
r
=
radeon_bo_pin_restricted
(
work
->
new_
rbo
,
RADEON_GEM_DOMAIN_VRAM
,
r
=
radeon_bo_pin_restricted
(
rbo
,
RADEON_GEM_DOMAIN_VRAM
,
ASIC_IS_AVIVO
(
rdev
)
?
0
:
1
<<
27
,
&
base
);
ASIC_IS_AVIVO
(
rdev
)
?
0
:
1
<<
27
,
&
base
);
if
(
unlikely
(
r
!=
0
))
{
if
(
unlikely
(
r
!=
0
))
{
radeon_bo_unreserve
(
work
->
new_
rbo
);
radeon_bo_unreserve
(
rbo
);
r
=
-
EINVAL
;
r
=
-
EINVAL
;
DRM_ERROR
(
"failed to pin new rbo buffer before flip
\n
"
);
DRM_ERROR
(
"failed to pin new rbo buffer before flip
\n
"
);
goto
cleanup
;
goto
pflip_
cleanup
;
}
}
radeon_bo_get_tiling_flags
(
work
->
new_
rbo
,
&
tiling_flags
,
NULL
);
radeon_bo_get_tiling_flags
(
rbo
,
&
tiling_flags
,
NULL
);
radeon_bo_unreserve
(
work
->
new_
rbo
);
radeon_bo_unreserve
(
rbo
);
if
(
!
ASIC_IS_AVIVO
(
rdev
))
{
if
(
!
ASIC_IS_AVIVO
(
rdev
))
{
/* crtc offset is from display base addr not FB location */
/* crtc offset is from display base addr not FB location */
...
@@ -455,91 +486,28 @@ static void radeon_flip_work_func(struct work_struct *__work)
...
@@ -455,91 +486,28 @@ static void radeon_flip_work_func(struct work_struct *__work)
base
&=
~
7
;
base
&=
~
7
;
}
}
/* We borrow the event spin lock for protecting flip_work */
spin_lock_irqsave
(
&
dev
->
event_lock
,
flags
);
spin_lock_irqsave
(
&
crtc
->
dev
->
event_lock
,
flags
);
work
->
new_crtc_base
=
base
;
spin_unlock_irqrestore
(
&
dev
->
event_lock
,
flags
);
/* set the proper interrupt */
radeon_irq_kms_pflip_irq_get
(
rdev
,
radeon_crtc
->
crtc_id
);
/* do the flip (mmio) */
radeon_page_flip
(
rdev
,
radeon_crtc
->
crtc_id
,
base
);
spin_unlock_irqrestore
(
&
crtc
->
dev
->
event_lock
,
flags
);
up_read
(
&
rdev
->
exclusive_lock
);
return
;
cleanup:
drm_gem_object_unreference_unlocked
(
&
work
->
old_rbo
->
gem_base
);
radeon_fence_unref
(
&
work
->
fence
);
kfree
(
work
);
up_read
(
&
rdev
->
exclusive_lock
);
}
static
int
radeon_crtc_page_flip
(
struct
drm_crtc
*
crtc
,
struct
drm_framebuffer
*
fb
,
struct
drm_pending_vblank_event
*
event
,
uint32_t
page_flip_flags
)
{
struct
drm_device
*
dev
=
crtc
->
dev
;
struct
radeon_device
*
rdev
=
dev
->
dev_private
;
struct
radeon_crtc
*
radeon_crtc
=
to_radeon_crtc
(
crtc
);
struct
radeon_framebuffer
*
old_radeon_fb
;
struct
radeon_framebuffer
*
new_radeon_fb
;
struct
drm_gem_object
*
obj
;
struct
radeon_flip_work
*
work
;
unsigned
long
flags
;
work
=
kzalloc
(
sizeof
*
work
,
GFP_KERNEL
);
if
(
work
==
NULL
)
return
-
ENOMEM
;
INIT_WORK
(
&
work
->
flip_work
,
radeon_flip_work_func
);
INIT_WORK
(
&
work
->
unpin_work
,
radeon_unpin_work_func
);
work
->
rdev
=
rdev
;
work
->
crtc_id
=
radeon_crtc
->
crtc_id
;
work
->
fb
=
fb
;
work
->
event
=
event
;
/* schedule unpin of the old buffer */
old_radeon_fb
=
to_radeon_framebuffer
(
crtc
->
primary
->
fb
);
obj
=
old_radeon_fb
->
obj
;
/* take a reference to the old object */
drm_gem_object_reference
(
obj
);
work
->
old_rbo
=
gem_to_radeon_bo
(
obj
);
new_radeon_fb
=
to_radeon_framebuffer
(
fb
);
obj
=
new_radeon_fb
->
obj
;
work
->
new_rbo
=
gem_to_radeon_bo
(
obj
);
spin_lock
(
&
work
->
new_rbo
->
tbo
.
bdev
->
fence_lock
);
if
(
work
->
new_rbo
->
tbo
.
sync_obj
)
work
->
fence
=
radeon_fence_ref
(
work
->
new_rbo
->
tbo
.
sync_obj
);
spin_unlock
(
&
work
->
new_rbo
->
tbo
.
bdev
->
fence_lock
);
/* update crtc fb */
/* update crtc fb */
crtc
->
primary
->
fb
=
fb
;
crtc
->
primary
->
fb
=
fb
;
/*
We borrow the event spin lock for protecting flip_work
*/
/*
set the proper interrupt
*/
spin_lock_irqsave
(
&
crtc
->
dev
->
event_lock
,
flags
);
radeon_irq_kms_pflip_irq_get
(
rdev
,
radeon_crtc
->
crtc_id
);
if
(
radeon_crtc
->
flip_work
)
{
return
0
;
DRM_DEBUG_DRIVER
(
"flip queue: crtc already busy
\n
"
);
spin_unlock_irqrestore
(
&
crtc
->
dev
->
event_lock
,
flags
);
pflip_cleanup:
drm_gem_object_unreference_unlocked
(
&
work
->
old_rbo
->
gem_base
);
spin_lock_irqsave
(
&
dev
->
event_lock
,
flags
);
radeon_crtc
->
unpin_work
=
NULL
;
unlock_free:
spin_unlock_irqrestore
(
&
dev
->
event_lock
,
flags
);
drm_gem_object_unreference_unlocked
(
old_radeon_fb
->
obj
);
radeon_fence_unref
(
&
work
->
fence
);
radeon_fence_unref
(
&
work
->
fence
);
kfree
(
work
);
kfree
(
work
);
return
-
EBUSY
;
}
radeon_crtc
->
flip_work
=
work
;
spin_unlock_irqrestore
(
&
crtc
->
dev
->
event_lock
,
flags
);
return
r
;
queue_work
(
radeon_crtc
->
flip_queue
,
&
work
->
flip_work
);
return
0
;
}
}
static
int
static
int
...
@@ -609,7 +577,6 @@ static void radeon_crtc_init(struct drm_device *dev, int index)
...
@@ -609,7 +577,6 @@ static void radeon_crtc_init(struct drm_device *dev, int index)
drm_mode_crtc_set_gamma_size
(
&
radeon_crtc
->
base
,
256
);
drm_mode_crtc_set_gamma_size
(
&
radeon_crtc
->
base
,
256
);
radeon_crtc
->
crtc_id
=
index
;
radeon_crtc
->
crtc_id
=
index
;
radeon_crtc
->
flip_queue
=
create_singlethread_workqueue
(
"radeon-crtc"
);
rdev
->
mode_info
.
crtcs
[
index
]
=
radeon_crtc
;
rdev
->
mode_info
.
crtcs
[
index
]
=
radeon_crtc
;
if
(
rdev
->
family
>=
CHIP_BONAIRE
)
{
if
(
rdev
->
family
>=
CHIP_BONAIRE
)
{
...
...
drivers/gpu/drm/radeon/radeon_mode.h
View file @
b15eb4ea
...
@@ -325,8 +325,8 @@ struct radeon_crtc {
...
@@ -325,8 +325,8 @@ struct radeon_crtc {
struct
drm_display_mode
native_mode
;
struct
drm_display_mode
native_mode
;
int
pll_id
;
int
pll_id
;
/* page flipping */
/* page flipping */
struct
workqueue_struct
*
flip_queue
;
struct
radeon_unpin_work
*
unpin_work
;
struct
radeon_flip_work
*
flip_work
;
int
deferred_flip_completion
;
/* pll sharing */
/* pll sharing */
struct
radeon_atom_ss
ss
;
struct
radeon_atom_ss
ss
;
bool
ss_enabled
;
bool
ss_enabled
;
...
...
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