drm/vc4: kms: Reduce firmware clock requests during atomic commits#7498
Draft
popcornmix wants to merge 1 commit into
Draft
drm/vc4: kms: Reduce firmware clock requests during atomic commits#7498popcornmix wants to merge 1 commit into
popcornmix wants to merge 1 commit into
Conversation
On Raspberry Pi the core clock is managed by the firmware, so every
clk_set_min_rate() call on it results in at least one blocking
mailbox round-trip to the VPU: the clock is registered with
CLK_GET_RATE_NOCACHE, so clk_set_rate_range() always queries the
current rate via GET_CLOCK_RATE, and issues a SET_CLOCK_RATE on top
if the aggregated rate changed. All of this happens under the global
clk prepare_lock.
vc4_atomic_commit_tail() currently requests a boost of the core clock
to at least 500MHz at the start of *every* commit and settles back to
the load-derived rate at the end, even though the boost is only needed
to avoid stalling the pipeline during a full modeset. In addition the
final drm_dbg() evaluated clk_get_rate() unconditionally, hiding
another firmware query. A compositor page-flipping at 60Hz therefore
generated several mailbox transactions per frame, all of them no-ops.
Fix this in two ways:
- Only apply the 500MHz floor when one of the CRTCs in the commit
actually needs a modeset. Plane-only updates still raise the clock
to the maximum of the old and new state requirements before the
HVS is reprogrammed, since the load can change without a modeset.
- Cache the last requested minimum rate in struct vc4_hvs and skip
requests that wouldn't change it. The core and display clocks are
always requested at the same rate, so a single cached value is
enough, and the actual-rate debug query now only happens when the
request really changes.
With this, steady-state page flips no longer generate any firmware
mailbox traffic, while modesets and genuine load changes behave as
before.
Signed-off-by: Dom Cobley <popcornmix@gmail.com>
Collaborator
Author
|
@XECDesign does this help your display latency testing. |
Contributor
|
The pi no longer reboot reliably, but when it does, the numbers are what you'd expect. I'll do a bit more testing to be 100% sure the patch is the problem, but it may be worth somebody else trying it as well. I'm seeing a boot failure about every 4th time. Black screen, probably not getting past the module load in initramfs. Edit: I don't think the reboot issue is caused by the patch. Still getting the same problem after reverting it. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
On Raspberry Pi the core clock is managed by the firmware, so every clk_set_min_rate() call on it results in at least one blocking mailbox round-trip to the VPU: the clock is registered with CLK_GET_RATE_NOCACHE, so clk_set_rate_range() always queries the current rate via GET_CLOCK_RATE, and issues a SET_CLOCK_RATE on top if the aggregated rate changed. All of this happens under the global clk prepare_lock.
vc4_atomic_commit_tail() currently requests a boost of the core clock to at least 500MHz at the start of every commit and settles back to the load-derived rate at the end, even though the boost is only needed to avoid stalling the pipeline during a full modeset. In addition the final drm_dbg() evaluated clk_get_rate() unconditionally, hiding another firmware query. A compositor page-flipping at 60Hz therefore generated several mailbox transactions per frame, all of them no-ops.
Fix this in two ways:
Only apply the 500MHz floor when one of the CRTCs in the commit actually needs a modeset. Plane-only updates still raise the clock to the maximum of the old and new state requirements before the HVS is reprogrammed, since the load can change without a modeset.
Cache the last requested minimum rate in struct vc4_hvs and skip requests that wouldn't change it. The core and display clocks are always requested at the same rate, so a single cached value is enough, and the actual-rate debug query now only happens when the request really changes.
With this, steady-state page flips no longer generate any firmware mailbox traffic, while modesets and genuine load changes behave as before.