These fix two atomic modesetting issues on v4.7-rc1. The last one is a bit of an RFC.
Changes to v1:
- drop unnecessary cleanups from "drm: make drm_atomic_set_mode_prop_for_crtc() more reliable". - Cc stable where appropriate - Add "Fixes:" to "drm: fix fb refcount issue with atomic modesetting"
Tomi
Tomi Valkeinen (4): drm: add missing drm_mode_set_crtcinfo call drm/sti: remove extra mode fixup drm: make drm_atomic_set_mode_prop_for_crtc() more reliable drm: fix fb refcount issue with atomic modesetting
drivers/gpu/drm/drm_atomic.c | 3 ++- drivers/gpu/drm/drm_crtc.c | 5 ++--- drivers/gpu/drm/drm_modes.c | 2 ++ drivers/gpu/drm/sti/sti_crtc.c | 10 ---------- 4 files changed, 6 insertions(+), 14 deletions(-)
When setting mode via MODE_ID property, drm_atomic_set_mode_prop_for_crtc() does not call drm_mode_set_crtcinfo() which possibly causes:
"[drm:drm_calc_timestamping_constants [drm]] *ERROR* crtc 32: Can't calculate constants, dotclock = 0!"
Whether the error is seen depends on the previous data in state->mode, as state->mode is not cleared when setting new mode.
This patch adds drm_mode_set_crtcinfo() call to drm_mode_convert_umode(), which is called in both legacy and atomic paths. This should be fine as there's no reason to call drm_mode_convert_umode() without also setting the crtc related fields.
drm_mode_set_crtcinfo() is removed from the legacy drm_mode_setcrtc() as that is no longer needed.
Signed-off-by: Tomi Valkeinen tomi.valkeinen@ti.com Reviewed-by: Daniel Vetter daniel.vetter@ffwll.ch Cc: stable@vger.kernel.org --- drivers/gpu/drm/drm_crtc.c | 2 -- drivers/gpu/drm/drm_modes.c | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index d2a6d958ca76..06b6e2173697 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -2821,8 +2821,6 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, goto out; }
- drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); - /* * Check whether the primary plane supports the fb pixel format. * Drivers not implementing the universal planes API use a diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 7def3d58da18..e5e6f504d8cc 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -1518,6 +1518,8 @@ int drm_mode_convert_umode(struct drm_display_mode *out, if (out->status != MODE_OK) goto out;
+ drm_mode_set_crtcinfo(out, CRTC_INTERLACE_HALVE_V); + ret = 0;
out:
Commit 652353e6e561c2aeeac62df183f721f6f9b5b45f ("drm/sti: set CRTC modesetting parameters") added a hack to avoid warnings related to setting mode with atomic API. With the previous patch, the hack should no longer be necessary.
Signed-off-by: Tomi Valkeinen tomi.valkeinen@ti.com Cc: Benjamin Gaignard benjamin.gaignard@linaro.org Cc: Vincent Abriou vincent.abriou@st.com Reviewed-by: Daniel Vetter daniel.vetter@ffwll.ch --- drivers/gpu/drm/sti/sti_crtc.c | 10 ---------- 1 file changed, 10 deletions(-)
diff --git a/drivers/gpu/drm/sti/sti_crtc.c b/drivers/gpu/drm/sti/sti_crtc.c index 505620c7c2c8..e04deedabd4a 100644 --- a/drivers/gpu/drm/sti/sti_crtc.c +++ b/drivers/gpu/drm/sti/sti_crtc.c @@ -51,15 +51,6 @@ static void sti_crtc_disabling(struct drm_crtc *crtc) mixer->status = STI_MIXER_DISABLING; }
-static bool sti_crtc_mode_fixup(struct drm_crtc *crtc, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - /* accept the provided drm_display_mode, do not fix it up */ - drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V); - return true; -} - static int sti_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode) { @@ -230,7 +221,6 @@ static void sti_crtc_atomic_flush(struct drm_crtc *crtc, static const struct drm_crtc_helper_funcs sti_crtc_helper_funcs = { .enable = sti_crtc_enable, .disable = sti_crtc_disabling, - .mode_fixup = sti_crtc_mode_fixup, .mode_set = drm_helper_crtc_mode_set, .mode_set_nofb = sti_crtc_mode_set_nofb, .mode_set_base = drm_helper_crtc_mode_set_base,
drm_atomic_set_mode_prop_for_crtc() does not clear the state->mode, so old data may be left there when a new mode is set, possibly causing odd issues.
This patch improves the situation by always clearing the state->mode first.
Signed-off-by: Tomi Valkeinen tomi.valkeinen@ti.com Cc: stable@vger.kernel.org --- drivers/gpu/drm/drm_atomic.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 3ff1ed7b33db..c204ef32df16 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -351,6 +351,8 @@ int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state, drm_property_unreference_blob(state->mode_blob); state->mode_blob = NULL;
+ memset(&state->mode, 0, sizeof(state->mode)); + if (blob) { if (blob->length != sizeof(struct drm_mode_modeinfo) || drm_mode_convert_umode(&state->mode, @@ -363,7 +365,6 @@ int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state, DRM_DEBUG_ATOMIC("Set [MODE:%s] for CRTC state %p\n", state->mode.name, state); } else { - memset(&state->mode, 0, sizeof(state->mode)); state->enable = false; DRM_DEBUG_ATOMIC("Set [NOMODE] for CRTC state %p\n", state);
On Tue, May 31, 2016 at 03:03:17PM +0300, Tomi Valkeinen wrote:
drm_atomic_set_mode_prop_for_crtc() does not clear the state->mode, so old data may be left there when a new mode is set, possibly causing odd issues.
This patch improves the situation by always clearing the state->mode first.
Signed-off-by: Tomi Valkeinen tomi.valkeinen@ti.com Cc: stable@vger.kernel.org
Reviewed-by: Daniel Vetter daniel.vetter@ffwll.ch
drivers/gpu/drm/drm_atomic.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 3ff1ed7b33db..c204ef32df16 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -351,6 +351,8 @@ int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state, drm_property_unreference_blob(state->mode_blob); state->mode_blob = NULL;
- memset(&state->mode, 0, sizeof(state->mode));
- if (blob) { if (blob->length != sizeof(struct drm_mode_modeinfo) || drm_mode_convert_umode(&state->mode,
@@ -363,7 +365,6 @@ int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state, DRM_DEBUG_ATOMIC("Set [MODE:%s] for CRTC state %p\n", state->mode.name, state); } else {
state->enable = false; DRM_DEBUG_ATOMIC("Set [NOMODE] for CRTC state %p\n", state);memset(&state->mode, 0, sizeof(state->mode));
-- 2.5.0
After commit 027b3f8ba9277410c3191d72d1ed2c6146d8a668 ("drm/modes: stop handling framebuffer special") extra fb refs are left around when doing atomic modesetting.
The problem is that the new drm_property_change_valid_get() does not return anything in the '**ref' parameter, which causes drm_property_change_valid_put() to do nothing.
For some reason this doesn't cause problems with legacy API.
Also, previously the code only set the 'ref' variable for fbs, with this patch the 'ref' is set for all objects.
Fixes: 027b3f8ba927 ("drm/modes: stop handling framebuffer special") Signed-off-by: Tomi Valkeinen tomi.valkeinen@ti.com Reviewed-by: Daniel Vetter daniel.vetter@ffwll.ch --- drivers/gpu/drm/drm_crtc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 06b6e2173697..0e3cc66aa8b7 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -4839,7 +4839,8 @@ bool drm_property_change_valid_get(struct drm_property *property, if (value == 0) return true;
- return _object_find(property->dev, value, property->values[0]) != NULL; + *ref = _object_find(property->dev, value, property->values[0]); + return *ref != NULL; }
for (i = 0; i < property->num_values; i++)
dri-devel@lists.freedesktop.org