* [PATCH v8 01/10] drm/amd/display: embed the writeback encoder in amdgpu_dm_wb_connector
2026-11-11 0:42 [PATCH v8 00/10] drm: writeback: clean up writeback connector initialization Dmitry Baryshkov
@ 2026-11-11 0:42 ` Dmitry Baryshkov
2026-11-11 0:42 ` [PATCH v8 02/10] drm/komeda: embed the writeback encoder in komeda_wb_connector Dmitry Baryshkov
` (8 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Dmitry Baryshkov @ 2026-11-11 0:42 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, John Harrison, Harry Wentland,
Leo Li, Rodrigo Siqueira, Alex Deucher, Christian König,
Liviu Dudau, Laurent Pinchart, Tomi Valkeinen, Kieran Bingham,
Geert Uytterhoeven, Magnus Damm, Dave Stevenson,
Maíra Canal, Raspberry Pi Kernel Maintenance, Louis Chauvet,
Mihail Atanassov, Eric Anholt, Rob Clark, Brian Starkey
Cc: dri-devel, linux-kernel, amd-gfx, linux-renesas-soc
drm_writeback_connector_init() hides the encoder inside struct
drm_writeback_connector, which is the only reason that structure carries
an encoder at all. Every other writeback user already owns its encoder.
Embed the encoder in the driver's own structure and register the
connector with drm_writeback_connector_init_with_encoder(), so that the
encoder can be dropped from drm_writeback_connector.
Reviewed-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +-
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 1 +
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c | 29 ++++++++++++++++------
.../amd/display/amdgpu_dm/tests/amdgpu_dm_test.c | 4 +--
.../display/amdgpu_dm/tests/amdgpu_dm_wb_test.c | 4 +--
5 files changed, 27 insertions(+), 13 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 0ea45ab12119..77788a2289fb 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -4812,7 +4812,7 @@ dm_set_writeback(struct amdgpu_display_manager *dm,
goto cleanup;
}
- acrtc = to_amdgpu_crtc(wb_conn->encoder.crtc);
+ acrtc = to_amdgpu_crtc(to_amdgpu_dm_wb_connector(wb_conn)->encoder.crtc);
if (!acrtc) {
drm_err(adev_to_drm(adev), "no amdgpu_crtc found\n");
goto cleanup;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
index 1b91fe4c3171..111bb110c439 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -935,6 +935,7 @@ static inline void amdgpu_dm_set_mst_status(uint8_t *status,
struct amdgpu_dm_wb_connector {
struct drm_writeback_connector base;
+ struct drm_encoder encoder;
struct dc_link *link;
};
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c
index 39b7b3e49f6b..e0ef23f692d4 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c
@@ -218,6 +218,10 @@ STATIC_IFN_KUNIT void amdgpu_dm_wb_cleanup_job(struct drm_writeback_connector *c
}
EXPORT_IF_KUNIT(amdgpu_dm_wb_cleanup_job);
+static const struct drm_encoder_funcs amdgpu_dm_wb_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
static const struct drm_encoder_helper_funcs amdgpu_dm_wb_encoder_helper_funcs = {
.atomic_check = amdgpu_dm_wb_encoder_atomic_check,
};
@@ -247,17 +251,26 @@ int amdgpu_dm_wb_connector_init(struct amdgpu_display_manager *dm,
wbcon->link = link;
- drm_connector_helper_add(&wbcon->base.base, &amdgpu_dm_wb_conn_helper_funcs);
-
- res = drm_writeback_connector_init(&dm->adev->ddev, &wbcon->base,
- &amdgpu_dm_wb_connector_funcs,
- &amdgpu_dm_wb_encoder_helper_funcs,
- amdgpu_dm_wb_formats,
- ARRAY_SIZE(amdgpu_dm_wb_formats),
- amdgpu_dm_get_encoder_crtc_mask(dm->adev));
+ drm_encoder_helper_add(&wbcon->encoder, &amdgpu_dm_wb_encoder_helper_funcs);
+ wbcon->encoder.possible_crtcs = amdgpu_dm_get_encoder_crtc_mask(dm->adev);
+ res = drm_encoder_init(&dm->adev->ddev, &wbcon->encoder,
+ &amdgpu_dm_wb_encoder_funcs,
+ DRM_MODE_ENCODER_VIRTUAL, NULL);
if (res)
return res;
+
+ drm_connector_helper_add(&wbcon->base.base, &amdgpu_dm_wb_conn_helper_funcs);
+
+ res = drm_writeback_connector_init_with_encoder(&dm->adev->ddev, &wbcon->base,
+ &wbcon->encoder,
+ &amdgpu_dm_wb_connector_funcs,
+ amdgpu_dm_wb_formats,
+ ARRAY_SIZE(amdgpu_dm_wb_formats));
+ if (res) {
+ drm_encoder_cleanup(&wbcon->encoder);
+ return res;
+ }
/*
* Some of the properties below require access to state, like bpc.
* Allocate some default initial connector state with our reset helper.
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_test.c
index e77e6fa18a72..e15db8c41662 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_test.c
@@ -4567,7 +4567,7 @@ static void dm_test_clear_writeback_removes_stream(struct kunit *test)
static void dm_test_set_writeback_no_pipe(struct kunit *test)
{
struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
- struct drm_writeback_connector *wb_conn;
+ struct amdgpu_dm_wb_connector *wb_conn;
struct drm_connector_state *conn_state;
struct drm_writeback_job *job;
struct amdgpu_framebuffer *afb;
@@ -4597,7 +4597,7 @@ static void dm_test_set_writeback_no_pipe(struct kunit *test)
conn_state->writeback_job = job;
crtc_state->stream = dm_kunit_alloc_stream(test, NULL);
- dm_set_writeback(&adev->dm, crtc_state, &wb_conn->base, conn_state);
+ dm_set_writeback(&adev->dm, crtc_state, &wb_conn->base.base, conn_state);
KUNIT_EXPECT_NULL(test, acrtc->wb_conn);
KUNIT_EXPECT_FALSE(test, acrtc->wb_pending);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_wb_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_wb_test.c
index b54624385e48..8359ef046c9c 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_wb_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_wb_test.c
@@ -510,8 +510,8 @@ static void dm_test_wb_connector_init_success(struct kunit *test)
KUNIT_EXPECT_TRUE(test, wbcon->base.base.funcs != NULL);
KUNIT_EXPECT_TRUE(test, wbcon->base.base.helper_private != NULL);
KUNIT_EXPECT_TRUE(test, wbcon->base.base.state != NULL);
- KUNIT_EXPECT_TRUE(test, wbcon->base.encoder.funcs != NULL);
- KUNIT_EXPECT_EQ(test, wbcon->base.encoder.possible_crtcs, 0x1);
+ KUNIT_EXPECT_NOT_NULL(test, wbcon->encoder.funcs);
+ KUNIT_EXPECT_EQ(test, wbcon->encoder.possible_crtcs, 0x1);
}
/* Tests for amdgpu_dm_wb_prepare_job / amdgpu_dm_wb_cleanup_job */
--
2.47.3
^ permalink raw reply [flat|nested] 11+ messages in thread* [PATCH v8 02/10] drm/komeda: embed the writeback encoder in komeda_wb_connector
2026-11-11 0:42 [PATCH v8 00/10] drm: writeback: clean up writeback connector initialization Dmitry Baryshkov
2026-11-11 0:42 ` [PATCH v8 01/10] drm/amd/display: embed the writeback encoder in amdgpu_dm_wb_connector Dmitry Baryshkov
@ 2026-11-11 0:42 ` Dmitry Baryshkov
2026-11-11 0:42 ` [PATCH v8 03/10] drm/mali: embed the writeback encoder in malidp_drm Dmitry Baryshkov
` (7 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Dmitry Baryshkov @ 2026-11-11 0:42 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, John Harrison, Harry Wentland,
Leo Li, Rodrigo Siqueira, Alex Deucher, Christian König,
Liviu Dudau, Laurent Pinchart, Tomi Valkeinen, Kieran Bingham,
Geert Uytterhoeven, Magnus Damm, Dave Stevenson,
Maíra Canal, Raspberry Pi Kernel Maintenance, Louis Chauvet,
Mihail Atanassov, Eric Anholt, Rob Clark, Brian Starkey
Cc: dri-devel, linux-kernel, amd-gfx, linux-renesas-soc
drm_writeback_connector_init() hides the encoder inside struct
drm_writeback_connector, which is the only reason that structure carries
an encoder at all. Every other writeback user already owns its encoder.
Embed the encoder in the driver's own structure and register the
connector with drm_writeback_connector_init_with_encoder(), so that the
encoder can be dropped from drm_writeback_connector.
Reviewed-by: Liviu Dudau <liviu.dudau@arm.com>
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
drivers/gpu/drm/arm/display/komeda/komeda_kms.h | 3 +++
.../drm/arm/display/komeda/komeda_wb_connector.c | 28 ++++++++++++++++------
2 files changed, 24 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.h b/drivers/gpu/drm/arm/display/komeda/komeda_kms.h
index 83e61c4080c2..4d41681a834b 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.h
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.h
@@ -56,6 +56,9 @@ struct komeda_wb_connector {
/** @base: &drm_writeback_connector */
struct drm_writeback_connector base;
+ /** @encoder: writeback encoder */
+ struct drm_encoder encoder;
+
/** @wb_layer: represents associated writeback pipeline of komeda */
struct komeda_layer *wb_layer;
};
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_wb_connector.c b/drivers/gpu/drm/arm/display/komeda/komeda_wb_connector.c
index f394971c0edb..7b795e1c5705 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_wb_connector.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_wb_connector.c
@@ -127,6 +127,10 @@ static void komeda_wb_connector_destroy(struct drm_connector *connector)
kfree(to_kconn(to_wb_conn(connector)));
}
+static const struct drm_encoder_funcs komeda_wb_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
static const struct drm_connector_funcs komeda_wb_connector_funcs = {
.atomic_create_state = drm_atomic_helper_connector_create_state,
.detect = komeda_wb_connector_detect,
@@ -170,18 +174,28 @@ static int komeda_wb_connector_add(struct komeda_kms_dev *kms,
return -ENOMEM;
}
- err = drm_writeback_connector_init(&kms->base, wb_conn,
- &komeda_wb_connector_funcs,
- &komeda_wb_encoder_helper_funcs,
- formats, n_formats,
- BIT(drm_crtc_index(&kcrtc->base)));
- komeda_put_fourcc_list(formats);
+ wb_encoder = &kwb_conn->encoder;
+ drm_encoder_helper_add(wb_encoder, &komeda_wb_encoder_helper_funcs);
+ wb_encoder->possible_crtcs = crtc_mask;
+
+ err = drm_encoder_init(&kms->base, wb_encoder, &komeda_wb_encoder_funcs,
+ DRM_MODE_ENCODER_VIRTUAL, NULL);
if (err) {
+ komeda_put_fourcc_list(formats);
kfree(kwb_conn);
return err;
}
- wb_encoder = &wb_conn->encoder;
+ err = drm_writeback_connector_init_with_encoder(&kms->base, wb_conn,
+ wb_encoder,
+ &komeda_wb_connector_funcs,
+ formats, n_formats);
+ komeda_put_fourcc_list(formats);
+ if (err) {
+ drm_encoder_cleanup(wb_encoder);
+ kfree(kwb_conn);
+ return err;
+ }
/*
* The writeback connector is associated with a single CRTC. Make its
--
2.47.3
^ permalink raw reply [flat|nested] 11+ messages in thread* [PATCH v8 03/10] drm/mali: embed the writeback encoder in malidp_drm
2026-11-11 0:42 [PATCH v8 00/10] drm: writeback: clean up writeback connector initialization Dmitry Baryshkov
2026-11-11 0:42 ` [PATCH v8 01/10] drm/amd/display: embed the writeback encoder in amdgpu_dm_wb_connector Dmitry Baryshkov
2026-11-11 0:42 ` [PATCH v8 02/10] drm/komeda: embed the writeback encoder in komeda_wb_connector Dmitry Baryshkov
@ 2026-11-11 0:42 ` Dmitry Baryshkov
2026-11-11 0:42 ` [PATCH v8 04/10] drm: renesas: rcar-du: embed the writeback encoder in rcar_du_crtc Dmitry Baryshkov
` (6 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Dmitry Baryshkov @ 2026-11-11 0:42 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, John Harrison, Harry Wentland,
Leo Li, Rodrigo Siqueira, Alex Deucher, Christian König,
Liviu Dudau, Laurent Pinchart, Tomi Valkeinen, Kieran Bingham,
Geert Uytterhoeven, Magnus Damm, Dave Stevenson,
Maíra Canal, Raspberry Pi Kernel Maintenance, Louis Chauvet,
Mihail Atanassov, Eric Anholt, Rob Clark, Brian Starkey
Cc: dri-devel, linux-kernel, amd-gfx, linux-renesas-soc
drm_writeback_connector_init() hides the encoder inside struct
drm_writeback_connector, which is the only reason that structure carries
an encoder at all. Every other writeback user already owns its encoder.
Embed the encoder in the driver's own structure and register the
connector with drm_writeback_connector_init_with_encoder(), so that the
encoder can be dropped from drm_writeback_connector.
Reviewed-by: Liviu Dudau <liviu.dudau@arm.com>
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
drivers/gpu/drm/arm/malidp_drv.h | 1 +
drivers/gpu/drm/arm/malidp_mw.c | 29 +++++++++++++++++++++++------
2 files changed, 24 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/arm/malidp_drv.h b/drivers/gpu/drm/arm/malidp_drv.h
index bc0387876dea..64610f2d23e2 100644
--- a/drivers/gpu/drm/arm/malidp_drv.h
+++ b/drivers/gpu/drm/arm/malidp_drv.h
@@ -33,6 +33,7 @@ struct malidp_drm {
struct malidp_hw_device *dev;
struct drm_crtc crtc;
struct drm_writeback_connector mw_connector;
+ struct drm_encoder mw_encoder;
wait_queue_head_t wq;
struct drm_pending_vblank_event *event;
atomic_t config_valid;
diff --git a/drivers/gpu/drm/arm/malidp_mw.c b/drivers/gpu/drm/arm/malidp_mw.c
index 8d1e1e3a6deb..889d0d1db85d 100644
--- a/drivers/gpu/drm/arm/malidp_mw.c
+++ b/drivers/gpu/drm/arm/malidp_mw.c
@@ -110,6 +110,10 @@ malidp_mw_connector_duplicate_state(struct drm_connector *connector)
return &mw_state->base;
}
+static const struct drm_encoder_funcs malidp_mw_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
static const struct drm_connector_funcs malidp_mw_connector_funcs = {
.atomic_create_state = malidp_mw_connector_create_state,
.detect = malidp_mw_connector_detect,
@@ -223,14 +227,27 @@ int malidp_mw_connector_init(struct drm_device *drm)
if (!formats)
return -ENOMEM;
- ret = drm_writeback_connector_init(drm, &malidp->mw_connector,
- &malidp_mw_connector_funcs,
- &malidp_mw_encoder_helper_funcs,
- formats, n_formats,
- 1 << drm_crtc_index(&malidp->crtc));
+ drm_encoder_helper_add(&malidp->mw_encoder,
+ &malidp_mw_encoder_helper_funcs);
+ malidp->mw_encoder.possible_crtcs = drm_crtc_mask(&malidp->crtc);
+
+ ret = drm_encoder_init(drm, &malidp->mw_encoder,
+ &malidp_mw_encoder_funcs,
+ DRM_MODE_ENCODER_VIRTUAL, NULL);
+ if (ret) {
+ kfree(formats);
+ return ret;
+ }
+
+ ret = drm_writeback_connector_init_with_encoder(drm, &malidp->mw_connector,
+ &malidp->mw_encoder,
+ &malidp_mw_connector_funcs,
+ formats, n_formats);
kfree(formats);
- if (ret)
+ if (ret) {
+ drm_encoder_cleanup(&malidp->mw_encoder);
return ret;
+ }
return 0;
}
--
2.47.3
^ permalink raw reply [flat|nested] 11+ messages in thread* [PATCH v8 04/10] drm: renesas: rcar-du: embed the writeback encoder in rcar_du_crtc
2026-11-11 0:42 [PATCH v8 00/10] drm: writeback: clean up writeback connector initialization Dmitry Baryshkov
` (2 preceding siblings ...)
2026-11-11 0:42 ` [PATCH v8 03/10] drm/mali: embed the writeback encoder in malidp_drm Dmitry Baryshkov
@ 2026-11-11 0:42 ` Dmitry Baryshkov
2026-11-11 0:42 ` [PATCH v8 05/10] drm: writeback: drop excess connector initialization functions Dmitry Baryshkov
` (5 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Dmitry Baryshkov @ 2026-11-11 0:42 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, John Harrison, Harry Wentland,
Leo Li, Rodrigo Siqueira, Alex Deucher, Christian König,
Liviu Dudau, Laurent Pinchart, Tomi Valkeinen, Kieran Bingham,
Geert Uytterhoeven, Magnus Damm, Dave Stevenson,
Maíra Canal, Raspberry Pi Kernel Maintenance, Louis Chauvet,
Mihail Atanassov, Eric Anholt, Rob Clark, Brian Starkey
Cc: dri-devel, linux-kernel, amd-gfx, linux-renesas-soc
drm_writeback_connector_init() hides the encoder inside struct
drm_writeback_connector, which is the only reason that structure carries
an encoder at all. Every other writeback user already owns its encoder.
Embed the encoder in the driver's own structure and register the
connector with drm_writeback_connector_init_with_encoder(), so that the
encoder can be dropped from drm_writeback_connector.
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
drivers/gpu/drm/renesas/rcar-du/rcar_du_crtc.h | 2 ++
.../gpu/drm/renesas/rcar-du/rcar_du_writeback.c | 29 +++++++++++++++++-----
2 files changed, 25 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/renesas/rcar-du/rcar_du_crtc.h b/drivers/gpu/drm/renesas/rcar-du/rcar_du_crtc.h
index 8857926e109a..d8b1dcab8dea 100644
--- a/drivers/gpu/drm/renesas/rcar-du/rcar_du_crtc.h
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_du_crtc.h
@@ -44,6 +44,7 @@ struct rcar_du_vsp;
* @vsp: VSP feeding video to this CRTC
* @vsp_pipe: index of the VSP pipeline feeding video to this CRTC
* @writeback: the writeback connector
+ * @encoder: the writeback encoder
*/
struct rcar_du_crtc {
struct drm_crtc crtc;
@@ -74,6 +75,7 @@ struct rcar_du_crtc {
unsigned int sources_count;
struct drm_writeback_connector writeback;
+ struct drm_encoder encoder;
};
#define to_rcar_crtc(c) container_of(c, struct rcar_du_crtc, crtc)
diff --git a/drivers/gpu/drm/renesas/rcar-du/rcar_du_writeback.c b/drivers/gpu/drm/renesas/rcar-du/rcar_du_writeback.c
index 0a3108965591..a1271fec9874 100644
--- a/drivers/gpu/drm/renesas/rcar-du/rcar_du_writeback.c
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_du_writeback.c
@@ -172,6 +172,10 @@ static int rcar_du_wb_enc_atomic_check(struct drm_encoder *encoder,
return 0;
}
+static const struct drm_encoder_funcs rcar_du_wb_enc_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
static const struct drm_encoder_helper_funcs rcar_du_wb_enc_helper_funcs = {
.atomic_check = rcar_du_wb_enc_atomic_check,
};
@@ -199,16 +203,29 @@ int rcar_du_writeback_init(struct rcar_du_device *rcdu,
struct rcar_du_crtc *rcrtc)
{
struct drm_writeback_connector *wb_conn = &rcrtc->writeback;
+ struct drm_encoder *encoder = &rcrtc->encoder;
+ int ret;
+
+ drm_encoder_helper_add(encoder, &rcar_du_wb_enc_helper_funcs);
+ encoder->possible_crtcs = drm_crtc_mask(&rcrtc->crtc);
+
+ ret = drm_encoder_init(&rcdu->ddev, encoder, &rcar_du_wb_enc_funcs,
+ DRM_MODE_ENCODER_VIRTUAL, NULL);
+ if (ret)
+ return ret;
drm_connector_helper_add(&wb_conn->base,
&rcar_du_wb_conn_helper_funcs);
- return drm_writeback_connector_init(&rcdu->ddev, wb_conn,
- &rcar_du_wb_conn_funcs,
- &rcar_du_wb_enc_helper_funcs,
- writeback_formats,
- ARRAY_SIZE(writeback_formats),
- 1 << drm_crtc_index(&rcrtc->crtc));
+ ret = drm_writeback_connector_init_with_encoder(&rcdu->ddev, wb_conn,
+ encoder,
+ &rcar_du_wb_conn_funcs,
+ writeback_formats,
+ ARRAY_SIZE(writeback_formats));
+ if (ret)
+ drm_encoder_cleanup(encoder);
+
+ return ret;
}
void rcar_du_writeback_setup(struct rcar_du_crtc *rcrtc,
--
2.47.3
^ permalink raw reply [flat|nested] 11+ messages in thread* [PATCH v8 05/10] drm: writeback: drop excess connector initialization functions
2026-11-11 0:42 [PATCH v8 00/10] drm: writeback: clean up writeback connector initialization Dmitry Baryshkov
` (3 preceding siblings ...)
2026-11-11 0:42 ` [PATCH v8 04/10] drm: renesas: rcar-du: embed the writeback encoder in rcar_du_crtc Dmitry Baryshkov
@ 2026-11-11 0:42 ` Dmitry Baryshkov
2026-11-11 0:42 ` [PATCH v8 06/10] drm: writeback: rename drm_writeback_connector_init_with_encoder() Dmitry Baryshkov
` (4 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Dmitry Baryshkov @ 2026-11-11 0:42 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, John Harrison, Harry Wentland,
Leo Li, Rodrigo Siqueira, Alex Deucher, Christian König,
Liviu Dudau, Laurent Pinchart, Tomi Valkeinen, Kieran Bingham,
Geert Uytterhoeven, Magnus Damm, Dave Stevenson,
Maíra Canal, Raspberry Pi Kernel Maintenance, Louis Chauvet,
Mihail Atanassov, Eric Anholt, Rob Clark, Brian Starkey
Cc: dri-devel, linux-kernel, amd-gfx, linux-renesas-soc, Suraj Kandpal
Now as all drivers have been converted to
drm_writeback_connector_init_with_encoder(), drop
drm_writeback_connector_init() and drm_writeback_connector::encoder
field, they are unused now.
Reviewed-by: Suraj Kandpal <suraj.kandpal@intel.com>
Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
drivers/gpu/drm/drm_writeback.c | 55 -----------------------------------------
include/drm/drm_writeback.h | 18 --------------
2 files changed, 73 deletions(-)
diff --git a/drivers/gpu/drm/drm_writeback.c b/drivers/gpu/drm/drm_writeback.c
index b4a002e6d043..683da368e339 100644
--- a/drivers/gpu/drm/drm_writeback.c
+++ b/drivers/gpu/drm/drm_writeback.c
@@ -148,61 +148,6 @@ static int create_writeback_properties(struct drm_device *dev)
return 0;
}
-static const struct drm_encoder_funcs drm_writeback_encoder_funcs = {
- .destroy = drm_encoder_cleanup,
-};
-
-/**
- * drm_writeback_connector_init - Initialize a writeback connector and its properties
- * @dev: DRM device
- * @wb_connector: Writeback connector to initialize
- * @con_funcs: Connector funcs vtable
- * @enc_helper_funcs: Encoder helper funcs vtable to be used by the internal encoder
- * @formats: Array of supported pixel formats for the writeback engine
- * @n_formats: Length of the formats array
- * @possible_crtcs: possible crtcs for the internal writeback encoder
- *
- * This function creates the writeback-connector-specific properties if they
- * have not been already created, initializes the connector as
- * type DRM_MODE_CONNECTOR_WRITEBACK, and correctly initializes the property
- * values. It will also create an internal encoder associated with the
- * drm_writeback_connector and set it to use the @enc_helper_funcs vtable for
- * the encoder helper.
- *
- * Drivers should always use this function instead of drm_connector_init() to
- * set up writeback connectors.
- *
- * Returns: 0 on success, or a negative error code
- */
-int drm_writeback_connector_init(struct drm_device *dev,
- struct drm_writeback_connector *wb_connector,
- const struct drm_connector_funcs *con_funcs,
- const struct drm_encoder_helper_funcs *enc_helper_funcs,
- const u32 *formats, int n_formats,
- u32 possible_crtcs)
-{
- int ret = 0;
-
- drm_encoder_helper_add(&wb_connector->encoder, enc_helper_funcs);
-
- wb_connector->encoder.possible_crtcs = possible_crtcs;
-
- ret = drm_encoder_init(dev, &wb_connector->encoder,
- &drm_writeback_encoder_funcs,
- DRM_MODE_ENCODER_VIRTUAL, NULL);
- if (ret)
- return ret;
-
- ret = drm_writeback_connector_init_with_encoder(dev, wb_connector, &wb_connector->encoder,
- con_funcs, formats, n_formats);
-
- if (ret)
- drm_encoder_cleanup(&wb_connector->encoder);
-
- return ret;
-}
-EXPORT_SYMBOL(drm_writeback_connector_init);
-
static void delete_writeback_properties(struct drm_device *dev)
{
if (dev->mode_config.writeback_pixel_formats_property) {
diff --git a/include/drm/drm_writeback.h b/include/drm/drm_writeback.h
index c380a7b8f55a..879ca103320c 100644
--- a/include/drm/drm_writeback.h
+++ b/include/drm/drm_writeback.h
@@ -24,17 +24,6 @@ struct drm_writeback_connector {
*/
struct drm_connector base;
- /**
- * @encoder: Internal encoder used by the connector to fulfill
- * the DRM framework requirements. The users of the
- * @drm_writeback_connector control the behaviour of the @encoder
- * by passing the @enc_funcs parameter to drm_writeback_connector_init()
- * function.
- * For users of drm_writeback_connector_init_with_encoder(), this field
- * is not valid as the encoder is managed within their drivers.
- */
- struct drm_encoder encoder;
-
/**
* @pixel_formats_blob_ptr:
*
@@ -148,13 +137,6 @@ drm_connector_to_writeback(struct drm_connector *connector)
return container_of(connector, struct drm_writeback_connector, base);
}
-int drm_writeback_connector_init(struct drm_device *dev,
- struct drm_writeback_connector *wb_connector,
- const struct drm_connector_funcs *con_funcs,
- const struct drm_encoder_helper_funcs *enc_helper_funcs,
- const u32 *formats, int n_formats,
- u32 possible_crtcs);
-
int drm_writeback_connector_init_with_encoder(struct drm_device *dev,
struct drm_writeback_connector *wb_connector,
struct drm_encoder *enc,
--
2.47.3
^ permalink raw reply [flat|nested] 11+ messages in thread* [PATCH v8 06/10] drm: writeback: rename drm_writeback_connector_init_with_encoder()
2026-11-11 0:42 [PATCH v8 00/10] drm: writeback: clean up writeback connector initialization Dmitry Baryshkov
` (4 preceding siblings ...)
2026-11-11 0:42 ` [PATCH v8 05/10] drm: writeback: drop excess connector initialization functions Dmitry Baryshkov
@ 2026-11-11 0:42 ` Dmitry Baryshkov
2026-11-11 0:42 ` [PATCH v8 07/10] drm: writeback: don't destroy the shared writeback properties Dmitry Baryshkov
` (3 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Dmitry Baryshkov @ 2026-11-11 0:42 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, John Harrison, Harry Wentland,
Leo Li, Rodrigo Siqueira, Alex Deucher, Christian König,
Liviu Dudau, Laurent Pinchart, Tomi Valkeinen, Kieran Bingham,
Geert Uytterhoeven, Magnus Damm, Dave Stevenson,
Maíra Canal, Raspberry Pi Kernel Maintenance, Louis Chauvet,
Mihail Atanassov, Eric Anholt, Rob Clark, Brian Starkey
Cc: dri-devel, linux-kernel, amd-gfx, linux-renesas-soc, Chaoyi Chen
Rename drm_writeback_connector_init_with_encoder() to
drm_writeback_connector_init() and adapt its interface to follow
drmm_writeback_connector_init(). Drop references to the "custom encoder"
from the documentation since it's now the only way to specify the
encoder to the writeback connector.
Reviewed-by: Chaoyi Chen <chaoyi.chen@rock-chips.com>
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c | 10 +++++-----
.../drm/arm/display/komeda/komeda_wb_connector.c | 8 ++++----
drivers/gpu/drm/arm/malidp_mw.c | 8 ++++----
drivers/gpu/drm/drm_writeback.c | 21 +++++++++------------
drivers/gpu/drm/renesas/rcar-du/rcar_du_writeback.c | 10 +++++-----
drivers/gpu/drm/vc4/vc4_txp.c | 8 ++++----
include/drm/drm_writeback.h | 10 +++++-----
7 files changed, 36 insertions(+), 39 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c
index e0ef23f692d4..dde02b2b018b 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c
@@ -262,11 +262,11 @@ int amdgpu_dm_wb_connector_init(struct amdgpu_display_manager *dm,
drm_connector_helper_add(&wbcon->base.base, &amdgpu_dm_wb_conn_helper_funcs);
- res = drm_writeback_connector_init_with_encoder(&dm->adev->ddev, &wbcon->base,
- &wbcon->encoder,
- &amdgpu_dm_wb_connector_funcs,
- amdgpu_dm_wb_formats,
- ARRAY_SIZE(amdgpu_dm_wb_formats));
+ res = drm_writeback_connector_init(&dm->adev->ddev, &wbcon->base,
+ &amdgpu_dm_wb_connector_funcs,
+ &wbcon->encoder,
+ amdgpu_dm_wb_formats,
+ ARRAY_SIZE(amdgpu_dm_wb_formats));
if (res) {
drm_encoder_cleanup(&wbcon->encoder);
return res;
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_wb_connector.c b/drivers/gpu/drm/arm/display/komeda/komeda_wb_connector.c
index 7b795e1c5705..ea4589b00ee0 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_wb_connector.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_wb_connector.c
@@ -186,10 +186,10 @@ static int komeda_wb_connector_add(struct komeda_kms_dev *kms,
return err;
}
- err = drm_writeback_connector_init_with_encoder(&kms->base, wb_conn,
- wb_encoder,
- &komeda_wb_connector_funcs,
- formats, n_formats);
+ err = drm_writeback_connector_init(&kms->base, wb_conn,
+ &komeda_wb_connector_funcs,
+ wb_encoder,
+ formats, n_formats);
komeda_put_fourcc_list(formats);
if (err) {
drm_encoder_cleanup(wb_encoder);
diff --git a/drivers/gpu/drm/arm/malidp_mw.c b/drivers/gpu/drm/arm/malidp_mw.c
index 889d0d1db85d..3669d10540bf 100644
--- a/drivers/gpu/drm/arm/malidp_mw.c
+++ b/drivers/gpu/drm/arm/malidp_mw.c
@@ -239,10 +239,10 @@ int malidp_mw_connector_init(struct drm_device *drm)
return ret;
}
- ret = drm_writeback_connector_init_with_encoder(drm, &malidp->mw_connector,
- &malidp->mw_encoder,
- &malidp_mw_connector_funcs,
- formats, n_formats);
+ ret = drm_writeback_connector_init(drm, &malidp->mw_connector,
+ &malidp_mw_connector_funcs,
+ &malidp->mw_encoder,
+ formats, n_formats);
kfree(formats);
if (ret) {
drm_encoder_cleanup(&malidp->mw_encoder);
diff --git a/drivers/gpu/drm/drm_writeback.c b/drivers/gpu/drm/drm_writeback.c
index 683da368e339..89c36f1414ce 100644
--- a/drivers/gpu/drm/drm_writeback.c
+++ b/drivers/gpu/drm/drm_writeback.c
@@ -165,8 +165,7 @@ static void delete_writeback_properties(struct drm_device *dev)
}
/**
- * __drm_writeback_connector_init - Initialize a writeback connector with
- * a custom encoder
+ * __drm_writeback_connector_init - Initialize a writeback connector
*
* @dev: DRM device
* @wb_connector: Writeback connector to initialize
@@ -241,8 +240,7 @@ static int __drm_writeback_connector_init(struct drm_device *dev,
}
/**
- * drm_writeback_connector_init_with_encoder - Initialize a writeback connector with
- * a custom encoder
+ * drm_writeback_connector_init - Initialize a writeback connector
*
* @dev: DRM device
* @wb_connector: Writeback connector to initialize
@@ -269,11 +267,11 @@ static int __drm_writeback_connector_init(struct drm_device *dev,
*
* Returns: 0 on success, or a negative error code
*/
-int drm_writeback_connector_init_with_encoder(struct drm_device *dev,
- struct drm_writeback_connector *wb_connector,
- struct drm_encoder *enc,
- const struct drm_connector_funcs *con_funcs,
- const u32 *formats, int n_formats)
+int drm_writeback_connector_init(struct drm_device *dev,
+ struct drm_writeback_connector *wb_connector,
+ const struct drm_connector_funcs *con_funcs,
+ struct drm_encoder *enc,
+ const u32 *formats, int n_formats)
{
struct drm_connector *connector = &wb_connector->base;
int ret;
@@ -290,7 +288,7 @@ int drm_writeback_connector_init_with_encoder(struct drm_device *dev,
return ret;
}
-EXPORT_SYMBOL(drm_writeback_connector_init_with_encoder);
+EXPORT_SYMBOL(drm_writeback_connector_init);
/**
* drm_writeback_connector_cleanup - Cleanup the writeback connector
@@ -320,8 +318,7 @@ static void drm_writeback_connector_cleanup(struct drm_device *dev,
}
/**
- * drmm_writeback_connector_init - Initialize a writeback connector with
- * a custom encoder
+ * drmm_writeback_connector_init - Initialize a writeback connector
*
* @dev: DRM device
* @wb_connector: Writeback connector to initialize
diff --git a/drivers/gpu/drm/renesas/rcar-du/rcar_du_writeback.c b/drivers/gpu/drm/renesas/rcar-du/rcar_du_writeback.c
index a1271fec9874..a88408124758 100644
--- a/drivers/gpu/drm/renesas/rcar-du/rcar_du_writeback.c
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_du_writeback.c
@@ -217,11 +217,11 @@ int rcar_du_writeback_init(struct rcar_du_device *rcdu,
drm_connector_helper_add(&wb_conn->base,
&rcar_du_wb_conn_helper_funcs);
- ret = drm_writeback_connector_init_with_encoder(&rcdu->ddev, wb_conn,
- encoder,
- &rcar_du_wb_conn_funcs,
- writeback_formats,
- ARRAY_SIZE(writeback_formats));
+ ret = drm_writeback_connector_init(&rcdu->ddev, wb_conn,
+ &rcar_du_wb_conn_funcs,
+ encoder,
+ writeback_formats,
+ ARRAY_SIZE(writeback_formats));
if (ret)
drm_encoder_cleanup(encoder);
diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c
index 642953cba25f..6ffc54d23d48 100644
--- a/drivers/gpu/drm/vc4/vc4_txp.c
+++ b/drivers/gpu/drm/vc4/vc4_txp.c
@@ -601,10 +601,10 @@ static int vc4_txp_bind(struct device *dev, struct device *master, void *data)
drm_connector_helper_add(&txp->connector.base,
&vc4_txp_connector_helper_funcs);
- ret = drm_writeback_connector_init_with_encoder(drm, &txp->connector,
- encoder,
- &vc4_txp_connector_funcs,
- drm_fmts, ARRAY_SIZE(drm_fmts));
+ ret = drm_writeback_connector_init(drm, &txp->connector,
+ &vc4_txp_connector_funcs,
+ encoder,
+ drm_fmts, ARRAY_SIZE(drm_fmts));
if (ret)
return ret;
diff --git a/include/drm/drm_writeback.h b/include/drm/drm_writeback.h
index 879ca103320c..958466a05e60 100644
--- a/include/drm/drm_writeback.h
+++ b/include/drm/drm_writeback.h
@@ -137,11 +137,11 @@ drm_connector_to_writeback(struct drm_connector *connector)
return container_of(connector, struct drm_writeback_connector, base);
}
-int drm_writeback_connector_init_with_encoder(struct drm_device *dev,
- struct drm_writeback_connector *wb_connector,
- struct drm_encoder *enc,
- const struct drm_connector_funcs *con_funcs, const u32 *formats,
- int n_formats);
+int drm_writeback_connector_init(struct drm_device *dev,
+ struct drm_writeback_connector *wb_connector,
+ const struct drm_connector_funcs *con_funcs,
+ struct drm_encoder *enc,
+ const u32 *formats, int n_formats);
int drmm_writeback_connector_init(struct drm_device *dev,
struct drm_writeback_connector *wb_connector,
--
2.47.3
^ permalink raw reply [flat|nested] 11+ messages in thread* [PATCH v8 07/10] drm: writeback: don't destroy the shared writeback properties
2026-11-11 0:42 [PATCH v8 00/10] drm: writeback: clean up writeback connector initialization Dmitry Baryshkov
` (5 preceding siblings ...)
2026-11-11 0:42 ` [PATCH v8 06/10] drm: writeback: rename drm_writeback_connector_init_with_encoder() Dmitry Baryshkov
@ 2026-11-11 0:42 ` Dmitry Baryshkov
2026-11-11 0:42 ` [PATCH v8 08/10] drm: writeback: clean up writeback jobs outside the job_lock Dmitry Baryshkov
` (2 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Dmitry Baryshkov @ 2026-11-11 0:42 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, John Harrison, Harry Wentland,
Leo Li, Rodrigo Siqueira, Alex Deucher, Christian König,
Liviu Dudau, Laurent Pinchart, Tomi Valkeinen, Kieran Bingham,
Geert Uytterhoeven, Magnus Damm, Dave Stevenson,
Maíra Canal, Raspberry Pi Kernel Maintenance, Louis Chauvet,
Mihail Atanassov, Eric Anholt, Rob Clark, Brian Starkey
Cc: dri-devel, linux-kernel, amd-gfx, linux-renesas-soc
The writeback properties are created once per device and attached to
every writeback connector. Nevertheless, a failing
__drm_writeback_connector_init() destroys all three of them. If an
earlier writeback connector has already been registered (komeda and
rcar-du create one per CRTC), it is left holding stale property
pointers. The drmm cleanup action likewise destroys them as soon as the
first connector goes away.
Leave the properties alone. They are on the device's property list, so
drm_mode_config_cleanup() destroys them together with all other
properties.
Fixes: 2f3f4a73631b ("drm: writeback: Add missing cleanup in case of initialization failure")
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
drivers/gpu/drm/drm_writeback.c | 34 ++++++----------------------------
1 file changed, 6 insertions(+), 28 deletions(-)
diff --git a/drivers/gpu/drm/drm_writeback.c b/drivers/gpu/drm/drm_writeback.c
index 89c36f1414ce..2f6a7b50336c 100644
--- a/drivers/gpu/drm/drm_writeback.c
+++ b/drivers/gpu/drm/drm_writeback.c
@@ -148,22 +148,6 @@ static int create_writeback_properties(struct drm_device *dev)
return 0;
}
-static void delete_writeback_properties(struct drm_device *dev)
-{
- if (dev->mode_config.writeback_pixel_formats_property) {
- drm_property_destroy(dev, dev->mode_config.writeback_pixel_formats_property);
- dev->mode_config.writeback_pixel_formats_property = NULL;
- }
- if (dev->mode_config.writeback_out_fence_ptr_property) {
- drm_property_destroy(dev, dev->mode_config.writeback_out_fence_ptr_property);
- dev->mode_config.writeback_out_fence_ptr_property = NULL;
- }
- if (dev->mode_config.writeback_fb_id_property) {
- drm_property_destroy(dev, dev->mode_config.writeback_fb_id_property);
- dev->mode_config.writeback_fb_id_property = NULL;
- }
-}
-
/**
* __drm_writeback_connector_init - Initialize a writeback connector
*
@@ -198,20 +182,18 @@ static int __drm_writeback_connector_init(struct drm_device *dev,
int ret = create_writeback_properties(dev);
if (ret != 0)
- goto failed_properties;
+ return ret;
connector->interlace_allowed = 0;
ret = drm_connector_attach_encoder(connector, enc);
if (ret)
- goto failed_properties;
+ return ret;
blob = drm_property_create_blob(dev, n_formats * sizeof(*formats),
formats);
- if (IS_ERR(blob)) {
- ret = PTR_ERR(blob);
- goto failed_properties;
- }
+ if (IS_ERR(blob))
+ return PTR_ERR(blob);
INIT_LIST_HEAD(&wb_connector->job_queue);
spin_lock_init(&wb_connector->job_lock);
@@ -234,9 +216,6 @@ static int __drm_writeback_connector_init(struct drm_device *dev,
wb_connector->pixel_formats_blob_ptr = blob;
return 0;
-failed_properties:
- delete_writeback_properties(dev);
- return ret;
}
/**
@@ -295,8 +274,8 @@ EXPORT_SYMBOL(drm_writeback_connector_init);
* @dev: DRM device
* @data: Pointer to the writeback connector to clean up
*
- * This will decrement the reference counter of blobs and destroy properties. It
- * will also clean the remaining jobs in this writeback connector. Caution: This helper will not
+ * This will decrement the reference counter of blobs. It will also clean the
+ * remaining jobs in this writeback connector. Caution: This helper will not
* clean up the attached encoder and the drm_connector.
*/
static void drm_writeback_connector_cleanup(struct drm_device *dev,
@@ -306,7 +285,6 @@ static void drm_writeback_connector_cleanup(struct drm_device *dev,
struct drm_writeback_job *pos, *n;
struct drm_writeback_connector *wb_connector = data;
- delete_writeback_properties(dev);
drm_property_blob_put(wb_connector->pixel_formats_blob_ptr);
spin_lock_irqsave(&wb_connector->job_lock, flags);
--
2.47.3
^ permalink raw reply [flat|nested] 11+ messages in thread* [PATCH v8 08/10] drm: writeback: clean up writeback jobs outside the job_lock
2026-11-11 0:42 [PATCH v8 00/10] drm: writeback: clean up writeback connector initialization Dmitry Baryshkov
` (6 preceding siblings ...)
2026-11-11 0:42 ` [PATCH v8 07/10] drm: writeback: don't destroy the shared writeback properties Dmitry Baryshkov
@ 2026-11-11 0:42 ` Dmitry Baryshkov
2026-11-11 0:42 ` [PATCH v8 09/10] drm: writeback: clean up writeback connectors in drm_connector_cleanup() Dmitry Baryshkov
2026-11-11 0:42 ` [PATCH v8 10/10] drm: writeback: drop the drmm writeback cleanup action Dmitry Baryshkov
9 siblings, 0 replies; 11+ messages in thread
From: Dmitry Baryshkov @ 2026-11-11 0:42 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, John Harrison, Harry Wentland,
Leo Li, Rodrigo Siqueira, Alex Deucher, Christian König,
Liviu Dudau, Laurent Pinchart, Tomi Valkeinen, Kieran Bingham,
Geert Uytterhoeven, Magnus Damm, Dave Stevenson,
Maíra Canal, Raspberry Pi Kernel Maintenance, Louis Chauvet,
Mihail Atanassov, Eric Anholt, Rob Clark, Brian Starkey
Cc: dri-devel, linux-kernel, amd-gfx, linux-renesas-soc
drm_writeback_connector_cleanup() frees the jobs left on the queue while
holding job_lock with interrupts disabled. drm_writeback_cleanup_job()
may sleep, though: dropping the last framebuffer reference takes
mode_config.idr_mutex and other mutexes, and a driver's
cleanup_writeback_job() hook (e.g. amdgpu) grabs a dma_resv ww_mutex.
Splice the queue onto a local list under the lock and free the jobs after
dropping it, so the sleeping work runs in process context.
Fixes: 1914ba2b91ea ("drm: writeback: Create drmm variants for drm_writeback_connector initialization")
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
drivers/gpu/drm/drm_writeback.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/drm_writeback.c b/drivers/gpu/drm/drm_writeback.c
index 2f6a7b50336c..6487f4a104f2 100644
--- a/drivers/gpu/drm/drm_writeback.c
+++ b/drivers/gpu/drm/drm_writeback.c
@@ -281,18 +281,21 @@ EXPORT_SYMBOL(drm_writeback_connector_init);
static void drm_writeback_connector_cleanup(struct drm_device *dev,
void *data)
{
- unsigned long flags;
- struct drm_writeback_job *pos, *n;
struct drm_writeback_connector *wb_connector = data;
+ struct drm_writeback_job *pos, *n;
+ unsigned long flags;
+ LIST_HEAD(jobs);
drm_property_blob_put(wb_connector->pixel_formats_blob_ptr);
spin_lock_irqsave(&wb_connector->job_lock, flags);
- list_for_each_entry_safe(pos, n, &wb_connector->job_queue, list_entry) {
+ list_splice_init(&wb_connector->job_queue, &jobs);
+ spin_unlock_irqrestore(&wb_connector->job_lock, flags);
+
+ list_for_each_entry_safe(pos, n, &jobs, list_entry) {
list_del(&pos->list_entry);
drm_writeback_cleanup_job(pos);
}
- spin_unlock_irqrestore(&wb_connector->job_lock, flags);
}
/**
--
2.47.3
^ permalink raw reply [flat|nested] 11+ messages in thread* [PATCH v8 09/10] drm: writeback: clean up writeback connectors in drm_connector_cleanup()
2026-11-11 0:42 [PATCH v8 00/10] drm: writeback: clean up writeback connector initialization Dmitry Baryshkov
` (7 preceding siblings ...)
2026-11-11 0:42 ` [PATCH v8 08/10] drm: writeback: clean up writeback jobs outside the job_lock Dmitry Baryshkov
@ 2026-11-11 0:42 ` Dmitry Baryshkov
2026-11-11 0:42 ` [PATCH v8 10/10] drm: writeback: drop the drmm writeback cleanup action Dmitry Baryshkov
9 siblings, 0 replies; 11+ messages in thread
From: Dmitry Baryshkov @ 2026-11-11 0:42 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, John Harrison, Harry Wentland,
Leo Li, Rodrigo Siqueira, Alex Deucher, Christian König,
Liviu Dudau, Laurent Pinchart, Tomi Valkeinen, Kieran Bingham,
Geert Uytterhoeven, Magnus Damm, Dave Stevenson,
Maíra Canal, Raspberry Pi Kernel Maintenance, Louis Chauvet,
Mihail Atanassov, Eric Anholt, Rob Clark, Brian Starkey
Cc: dri-devel, linux-kernel, amd-gfx, linux-renesas-soc
Only drmm_writeback_connector_init() registers
drm_writeback_connector_cleanup(). Connectors set up with
drm_writeback_connector_init() (amdgpu, komeda, malidp, rcar-du, vc4)
never drop the formats blob or free the jobs still on the queue, leaking
them together with their framebuffer and fence references.
Call drm_writeback_connector_cleanup() from drm_connector_cleanup() so it
runs for both kinds of initialization, the same way the HDMI audio and
SCDC state is torn down there. It downcasts the connector to its
drm_writeback_connector wrapper, which is only valid when the connector
really is embedded in one. A plain drm_connector (or a different wrapper
struct) may be initialized with DRM_MODE_CONNECTOR_WRITEBACK without being
a writeback connector, as several KUnit tests do, so keying the cleanup
off the connector type would read out of bounds. Track genuine writeback
initialization with a drm_connector::wb_initialized flag set by
__drm_writeback_connector_init() and clean up based on it instead. The
drmm action now just wraps the helper; clearing the flag makes the second
invocation a no-op and also covers drm_connector_cleanup() being called
after a failed __drm_writeback_connector_init().
Fixes: 935774cd71fe ("drm: Add writeback connector type")
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
drivers/gpu/drm/drm_connector.c | 3 +++
drivers/gpu/drm/drm_crtc_internal.h | 3 +++
drivers/gpu/drm/drm_writeback.c | 30 ++++++++++++++++++++++++------
include/drm/drm_connector.h | 12 ++++++++++++
4 files changed, 42 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index d66188521881..da0b16f25ac4 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -921,6 +921,9 @@ void drm_connector_cleanup(struct drm_connector *connector)
if (connector->hdmi.scdc_work_initialized)
cancel_delayed_work_sync(&connector->hdmi.scdc_work);
+ if (connector->wb_initialized)
+ drm_writeback_connector_cleanup(connector);
+
platform_device_unregister(connector->hdmi_audio.codec_pdev);
if (connector->privacy_screen) {
diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h
index 3492787c3697..f60216adcd31 100644
--- a/drivers/gpu/drm/drm_crtc_internal.h
+++ b/drivers/gpu/drm/drm_crtc_internal.h
@@ -329,4 +329,7 @@ static inline void drm_panic_unregister(struct drm_device *dev) {}
static inline void drm_panic_init(void) {}
#endif
+/* drm_writeback.c */
+void drm_writeback_connector_cleanup(struct drm_connector *connector);
+
#endif /* __DRM_CRTC_INTERNAL_H__ */
diff --git a/drivers/gpu/drm/drm_writeback.c b/drivers/gpu/drm/drm_writeback.c
index 6487f4a104f2..6ea3e55a1962 100644
--- a/drivers/gpu/drm/drm_writeback.c
+++ b/drivers/gpu/drm/drm_writeback.c
@@ -21,6 +21,8 @@
#include <drm/drm_property.h>
#include <drm/drm_writeback.h>
+#include "drm_crtc_internal.h"
+
/**
* DOC: overview
*
@@ -215,6 +217,8 @@ static int __drm_writeback_connector_init(struct drm_device *dev,
blob->base.id);
wb_connector->pixel_formats_blob_ptr = blob;
+ connector->wb_initialized = true;
+
return 0;
}
@@ -271,22 +275,28 @@ EXPORT_SYMBOL(drm_writeback_connector_init);
/**
* drm_writeback_connector_cleanup - Cleanup the writeback connector
- * @dev: DRM device
- * @data: Pointer to the writeback connector to clean up
+ * @connector: Writeback connector to clean up
*
* This will decrement the reference counter of blobs. It will also clean the
* remaining jobs in this writeback connector. Caution: This helper will not
* clean up the attached encoder and the drm_connector.
+ *
+ * Called from drm_connector_cleanup() for all writeback connectors.
*/
-static void drm_writeback_connector_cleanup(struct drm_device *dev,
- void *data)
+void drm_writeback_connector_cleanup(struct drm_connector *connector)
{
- struct drm_writeback_connector *wb_connector = data;
+ struct drm_writeback_connector *wb_connector =
+ drm_connector_to_writeback(connector);
struct drm_writeback_job *pos, *n;
unsigned long flags;
LIST_HEAD(jobs);
+ if (!connector->wb_initialized)
+ return;
+ connector->wb_initialized = false;
+
drm_property_blob_put(wb_connector->pixel_formats_blob_ptr);
+ wb_connector->pixel_formats_blob_ptr = NULL;
spin_lock_irqsave(&wb_connector->job_lock, flags);
list_splice_init(&wb_connector->job_queue, &jobs);
@@ -298,6 +308,14 @@ static void drm_writeback_connector_cleanup(struct drm_device *dev,
}
}
+static void drm_writeback_connector_cleanup_action(struct drm_device *dev,
+ void *data)
+{
+ struct drm_writeback_connector *wb_connector = data;
+
+ drm_writeback_connector_cleanup(&wb_connector->base);
+}
+
/**
* drmm_writeback_connector_init - Initialize a writeback connector
*
@@ -336,7 +354,7 @@ int drmm_writeback_connector_init(struct drm_device *dev,
if (ret)
return ret;
- ret = drmm_add_action_or_reset(dev, drm_writeback_connector_cleanup,
+ ret = drmm_add_action_or_reset(dev, drm_writeback_connector_cleanup_action,
wb_connector);
if (ret)
return ret;
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index f656ed8324d3..07218ab26c9e 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -2688,6 +2688,18 @@ struct drm_connector {
*/
struct llist_node free_node;
+ /**
+ * @wb_initialized:
+ *
+ * Set when the connector is embedded in a &struct
+ * drm_writeback_connector that has been initialized through
+ * __drm_writeback_connector_init(). A plain &struct drm_connector may
+ * be created with DRM_MODE_CONNECTOR_WRITEBACK without being a
+ * writeback connector, so drm_connector_cleanup() keys the writeback
+ * teardown off this flag rather than the connector type.
+ */
+ bool wb_initialized;
+
/**
* @hdmi: HDMI-related variable and properties.
*/
--
2.47.3
^ permalink raw reply [flat|nested] 11+ messages in thread* [PATCH v8 10/10] drm: writeback: drop the drmm writeback cleanup action
2026-11-11 0:42 [PATCH v8 00/10] drm: writeback: clean up writeback connector initialization Dmitry Baryshkov
` (8 preceding siblings ...)
2026-11-11 0:42 ` [PATCH v8 09/10] drm: writeback: clean up writeback connectors in drm_connector_cleanup() Dmitry Baryshkov
@ 2026-11-11 0:42 ` Dmitry Baryshkov
9 siblings, 0 replies; 11+ messages in thread
From: Dmitry Baryshkov @ 2026-11-11 0:42 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, John Harrison, Harry Wentland,
Leo Li, Rodrigo Siqueira, Alex Deucher, Christian König,
Liviu Dudau, Laurent Pinchart, Tomi Valkeinen, Kieran Bingham,
Geert Uytterhoeven, Magnus Damm, Dave Stevenson,
Maíra Canal, Raspberry Pi Kernel Maintenance, Louis Chauvet,
Mihail Atanassov, Eric Anholt, Rob Clark, Brian Starkey
Cc: dri-devel, linux-kernel, amd-gfx, linux-renesas-soc, John Harrison
drmm_connector_init() already registers drm_connector_cleanup() as a
managed action, and that now cleans up the writeback state too. The
extra action registered by drmm_writeback_connector_init() just does the
same work a little earlier, leaving drm_connector_cleanup() nothing to
do. Drop it.
Reviewed-by: John Harrison <John.Harrison@Igalia.com>
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
drivers/gpu/drm/drm_writeback.c | 25 ++++---------------------
1 file changed, 4 insertions(+), 21 deletions(-)
diff --git a/drivers/gpu/drm/drm_writeback.c b/drivers/gpu/drm/drm_writeback.c
index 6ea3e55a1962..097d480d6187 100644
--- a/drivers/gpu/drm/drm_writeback.c
+++ b/drivers/gpu/drm/drm_writeback.c
@@ -16,7 +16,6 @@
#include <drm/drm_device.h>
#include <drm/drm_drv.h>
#include <drm/drm_framebuffer.h>
-#include <drm/drm_managed.h>
#include <drm/drm_modeset_helper_vtables.h>
#include <drm/drm_property.h>
#include <drm/drm_writeback.h>
@@ -308,14 +307,6 @@ void drm_writeback_connector_cleanup(struct drm_connector *connector)
}
}
-static void drm_writeback_connector_cleanup_action(struct drm_device *dev,
- void *data)
-{
- struct drm_writeback_connector *wb_connector = data;
-
- drm_writeback_connector_cleanup(&wb_connector->base);
-}
-
/**
* drmm_writeback_connector_init - Initialize a writeback connector
*
@@ -326,7 +317,8 @@ static void drm_writeback_connector_cleanup_action(struct drm_device *dev,
* @formats: Array of supported pixel formats for the writeback engine
* @n_formats: Length of the formats array
*
- * This function initialize a writeback connector and register its cleanup.
+ * This function initializes a writeback connector. Cleanup is automatically
+ * handled with a call to drm_connector_cleanup() in a DRM-managed action.
*
* This function creates the writeback-connector-specific properties if they
* have not been already created, initializes the connector as
@@ -349,17 +341,8 @@ int drmm_writeback_connector_init(struct drm_device *dev,
if (ret)
return ret;
- ret = __drm_writeback_connector_init(dev, wb_connector, enc, formats,
- n_formats);
- if (ret)
- return ret;
-
- ret = drmm_add_action_or_reset(dev, drm_writeback_connector_cleanup_action,
- wb_connector);
- if (ret)
- return ret;
-
- return 0;
+ return __drm_writeback_connector_init(dev, wb_connector, enc, formats,
+ n_formats);
}
EXPORT_SYMBOL(drmm_writeback_connector_init);
--
2.47.3
^ permalink raw reply [flat|nested] 11+ messages in thread