* [PATCH v7 1/9] drm/amd/display: embed the writeback encoder in amdgpu_dm_wb_connector
2026-10-19 13:12 [PATCH v7 0/9] drm: writeback: clean up writeback connector initialization Dmitry Baryshkov
@ 2026-10-19 13:12 ` Dmitry Baryshkov
2026-10-19 13:12 ` [PATCH v7 2/9] drm/komeda: embed the writeback encoder in komeda_wb_connector Dmitry Baryshkov
` (8 subsequent siblings)
9 siblings, 0 replies; 14+ messages in thread
From: Dmitry Baryshkov @ 2026-10-19 13:12 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.
Assisted-by: LLM
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 5e106b65034d..07dd69b42e83 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -4805,7 +4805,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 1d256dce0e4b..d365370d9958 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -930,6 +930,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 6f91a992d43f..b5b186e4f81c 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,
};
@@ -246,17 +250,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 e27f6e504395..9d237f2db95c 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
@@ -4535,7 +4535,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;
@@ -4565,7 +4565,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 03036f906385..2711696f6b9c 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
@@ -506,8 +506,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_TRUE(test, wbcon->encoder.funcs != NULL);
+ 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 related [flat|nested] 14+ messages in thread* [PATCH v7 2/9] drm/komeda: embed the writeback encoder in komeda_wb_connector
2026-10-19 13:12 [PATCH v7 0/9] drm: writeback: clean up writeback connector initialization Dmitry Baryshkov
2026-10-19 13:12 ` [PATCH v7 1/9] drm/amd/display: embed the writeback encoder in amdgpu_dm_wb_connector Dmitry Baryshkov
@ 2026-10-19 13:12 ` Dmitry Baryshkov
2026-10-19 13:12 ` [PATCH v7 3/9] drm/mali: embed the writeback encoder in malidp_drm Dmitry Baryshkov
` (7 subsequent siblings)
9 siblings, 0 replies; 14+ messages in thread
From: Dmitry Baryshkov @ 2026-10-19 13:12 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.
Assisted-by: LLM
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 4872253a2449..77aecf4d3f09 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 = {
.reset = drm_atomic_helper_connector_reset,
.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 related [flat|nested] 14+ messages in thread* [PATCH v7 3/9] drm/mali: embed the writeback encoder in malidp_drm
2026-10-19 13:12 [PATCH v7 0/9] drm: writeback: clean up writeback connector initialization Dmitry Baryshkov
2026-10-19 13:12 ` [PATCH v7 1/9] drm/amd/display: embed the writeback encoder in amdgpu_dm_wb_connector Dmitry Baryshkov
2026-10-19 13:12 ` [PATCH v7 2/9] drm/komeda: embed the writeback encoder in komeda_wb_connector Dmitry Baryshkov
@ 2026-10-19 13:12 ` Dmitry Baryshkov
2026-10-19 13:12 ` [PATCH v7 4/9] drm: renesas: rcar-du: embed the writeback encoder in rcar_du_crtc Dmitry Baryshkov
` (6 subsequent siblings)
9 siblings, 0 replies; 14+ messages in thread
From: Dmitry Baryshkov @ 2026-10-19 13:12 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.
Assisted-by: LLM
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 f8be65119e3b..7f5e25adf999 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 = {
.reset = malidp_mw_connector_reset,
.detect = malidp_mw_connector_detect,
@@ -224,14 +228,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 related [flat|nested] 14+ messages in thread* [PATCH v7 4/9] drm: renesas: rcar-du: embed the writeback encoder in rcar_du_crtc
2026-10-19 13:12 [PATCH v7 0/9] drm: writeback: clean up writeback connector initialization Dmitry Baryshkov
` (2 preceding siblings ...)
2026-10-19 13:12 ` [PATCH v7 3/9] drm/mali: embed the writeback encoder in malidp_drm Dmitry Baryshkov
@ 2026-10-19 13:12 ` Dmitry Baryshkov
2026-10-19 13:12 ` [PATCH v7 5/9] drm: writeback: drop excess connector initialization functions Dmitry Baryshkov
` (5 subsequent siblings)
9 siblings, 0 replies; 14+ messages in thread
From: Dmitry Baryshkov @ 2026-10-19 13:12 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.
Assisted-by: LLM
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 e5e6e6a156aa..b0c1ca0d0dfa 100644
--- a/drivers/gpu/drm/renesas/rcar-du/rcar_du_writeback.c
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_du_writeback.c
@@ -174,6 +174,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,
};
@@ -201,16 +205,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 related [flat|nested] 14+ messages in thread* [PATCH v7 5/9] drm: writeback: drop excess connector initialization functions
2026-10-19 13:12 [PATCH v7 0/9] drm: writeback: clean up writeback connector initialization Dmitry Baryshkov
` (3 preceding siblings ...)
2026-10-19 13:12 ` [PATCH v7 4/9] drm: renesas: rcar-du: embed the writeback encoder in rcar_du_crtc Dmitry Baryshkov
@ 2026-10-19 13:12 ` Dmitry Baryshkov
2026-10-19 13:12 ` [PATCH v7 6/9] drm: writeback: rename drm_writeback_connector_init_with_encoder() Dmitry Baryshkov
` (4 subsequent siblings)
9 siblings, 0 replies; 14+ messages in thread
From: Dmitry Baryshkov @ 2026-10-19 13:12 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 related [flat|nested] 14+ messages in thread* [PATCH v7 6/9] drm: writeback: rename drm_writeback_connector_init_with_encoder()
2026-10-19 13:12 [PATCH v7 0/9] drm: writeback: clean up writeback connector initialization Dmitry Baryshkov
` (4 preceding siblings ...)
2026-10-19 13:12 ` [PATCH v7 5/9] drm: writeback: drop excess connector initialization functions Dmitry Baryshkov
@ 2026-10-19 13:12 ` Dmitry Baryshkov
2026-10-20 1:22 ` Chaoyi Chen
2026-10-19 13:12 ` [PATCH v7 7/9] drm: writeback: don't destroy the shared writeback properties Dmitry Baryshkov
` (3 subsequent siblings)
9 siblings, 1 reply; 14+ messages in thread
From: Dmitry Baryshkov @ 2026-10-19 13:12 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
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.
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 b5b186e4f81c..18bee44794ce 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
@@ -261,11 +261,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 77aecf4d3f09..7c64facfd799 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 7f5e25adf999..7e1d1c0988ae 100644
--- a/drivers/gpu/drm/arm/malidp_mw.c
+++ b/drivers/gpu/drm/arm/malidp_mw.c
@@ -240,10 +240,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 b0c1ca0d0dfa..35460a314a7f 100644
--- a/drivers/gpu/drm/renesas/rcar-du/rcar_du_writeback.c
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_du_writeback.c
@@ -219,11 +219,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 c469f8b1068b..33b1bc37b362 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 related [flat|nested] 14+ messages in thread* Re: [PATCH v7 6/9] drm: writeback: rename drm_writeback_connector_init_with_encoder()
2026-10-19 13:12 ` [PATCH v7 6/9] drm: writeback: rename drm_writeback_connector_init_with_encoder() Dmitry Baryshkov
@ 2026-10-20 1:22 ` Chaoyi Chen
0 siblings, 0 replies; 14+ messages in thread
From: Chaoyi Chen @ 2026-10-20 1:22 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: 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, dri-devel, linux-kernel,
amd-gfx, linux-renesas-soc
On 10/19/2026 9:12 PM, Dmitry Baryshkov wrote:
> 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.
>
> 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 b5b186e4f81c..18bee44794ce 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
> @@ -261,11 +261,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 77aecf4d3f09..7c64facfd799 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 7f5e25adf999..7e1d1c0988ae 100644
> --- a/drivers/gpu/drm/arm/malidp_mw.c
> +++ b/drivers/gpu/drm/arm/malidp_mw.c
> @@ -240,10 +240,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 b0c1ca0d0dfa..35460a314a7f 100644
> --- a/drivers/gpu/drm/renesas/rcar-du/rcar_du_writeback.c
> +++ b/drivers/gpu/drm/renesas/rcar-du/rcar_du_writeback.c
> @@ -219,11 +219,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 c469f8b1068b..33b1bc37b362 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,
>
Looks good to me.
Reviewed-by: Chaoyi Chen <chaoyi.chen@rock-chips.com>
--
Best,
Chaoyi
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v7 7/9] drm: writeback: don't destroy the shared writeback properties
2026-10-19 13:12 [PATCH v7 0/9] drm: writeback: clean up writeback connector initialization Dmitry Baryshkov
` (5 preceding siblings ...)
2026-10-19 13:12 ` [PATCH v7 6/9] drm: writeback: rename drm_writeback_connector_init_with_encoder() Dmitry Baryshkov
@ 2026-10-19 13:12 ` Dmitry Baryshkov
2026-10-20 1:28 ` Chaoyi Chen
2026-10-19 13:12 ` [PATCH v7 8/9] drm: writeback: clean up writeback connectors in drm_connector_cleanup() Dmitry Baryshkov
` (2 subsequent siblings)
9 siblings, 1 reply; 14+ messages in thread
From: Dmitry Baryshkov @ 2026-10-19 13:12 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")
Assisted-by: LLM
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 related [flat|nested] 14+ messages in thread* Re: [PATCH v7 7/9] drm: writeback: don't destroy the shared writeback properties
2026-10-19 13:12 ` [PATCH v7 7/9] drm: writeback: don't destroy the shared writeback properties Dmitry Baryshkov
@ 2026-10-20 1:28 ` Chaoyi Chen
0 siblings, 0 replies; 14+ messages in thread
From: Chaoyi Chen @ 2026-10-20 1:28 UTC (permalink / raw)
To: Dmitry Baryshkov, John Harrison
Cc: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, 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, dri-devel, linux-kernel, amd-gfx,
linux-renesas-soc
Hi Dmitry,
On 10/19/2026 9:12 PM, Dmitry Baryshkov wrote:
> 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.
>
If a user attaches a private property to a connector, are they
responsible for calling put on that property during cleanup?
In that case, can drmm* functions be used to clean up these
properties? Thank you.
> Fixes: 2f3f4a73631b ("drm: writeback: Add missing cleanup in case of initialization failure")
> Assisted-by: LLM
> 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);
>
--
Best,
Chaoyi
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v7 8/9] drm: writeback: clean up writeback connectors in drm_connector_cleanup()
2026-10-19 13:12 [PATCH v7 0/9] drm: writeback: clean up writeback connector initialization Dmitry Baryshkov
` (6 preceding siblings ...)
2026-10-19 13:12 ` [PATCH v7 7/9] drm: writeback: don't destroy the shared writeback properties Dmitry Baryshkov
@ 2026-10-19 13:12 ` Dmitry Baryshkov
2026-10-19 13:30 ` sashiko-bot
2026-10-19 13:12 ` [PATCH v7 9/9] drm: writeback: drop the drmm writeback cleanup action Dmitry Baryshkov
2026-10-19 19:40 ` [PATCH v7 0/9] drm: writeback: clean up writeback connector initialization John Harrison
9 siblings, 1 reply; 14+ messages in thread
From: Dmitry Baryshkov @ 2026-10-19 13:12 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() for
writeback connectors, the same way the HDMI audio and SCDC state is torn
down there, so it runs for both kinds of initialization. The drmm action
now just wraps it. Clearing the blob pointer 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")
Assisted-by: LLM
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 +++++++++++++++++++++++-------
3 files changed, 29 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index 893716a9e489..1c2bef5e0636 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -929,6 +929,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->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
+ 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 2f6a7b50336c..272012a70efe 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
*
@@ -271,21 +273,27 @@ 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)
{
- unsigned long flags;
+ struct drm_writeback_connector *wb_connector =
+ drm_connector_to_writeback(connector);
struct drm_writeback_job *pos, *n;
- struct drm_writeback_connector *wb_connector = data;
+ unsigned long flags;
+
+ /* __drm_writeback_connector_init() has failed */
+ if (!wb_connector->pixel_formats_blob_ptr)
+ return;
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_for_each_entry_safe(pos, n, &wb_connector->job_queue, list_entry) {
@@ -295,6 +303,14 @@ static void drm_writeback_connector_cleanup(struct drm_device *dev,
spin_unlock_irqrestore(&wb_connector->job_lock, flags);
}
+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
*
@@ -333,7 +349,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;
--
2.47.3
^ permalink raw reply related [flat|nested] 14+ messages in thread* Re: [PATCH v7 8/9] drm: writeback: clean up writeback connectors in drm_connector_cleanup()
2026-10-19 13:12 ` [PATCH v7 8/9] drm: writeback: clean up writeback connectors in drm_connector_cleanup() Dmitry Baryshkov
@ 2026-10-19 13:30 ` sashiko-bot
0 siblings, 0 replies; 14+ messages in thread
From: sashiko-bot @ 2026-10-19 13:30 UTC (permalink / raw)
To: Dmitry Baryshkov; +Cc: dri-devel, wsa+renesas
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] drm: out-of-bounds access in drm_writeback_connector_cleanup() downcast
- [High] drm: writeback: drm_writeback_cleanup_job() called under spin_lock_irqsave()
--
commit 01e86ffc01bb0a8fee1f22a88d9725baf85bf61d
Author: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
drm: writeback: clean up writeback connectors in drm_connector_cleanup()
This commit calls drm_writeback_connector_cleanup() from
drm_connector_cleanup() for writeback connectors so that connectors
initialized with drm_writeback_connector_init() also drop their formats
blob and clean up queued writeback jobs upon teardown.
> diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
> index 893716a9e4895..1c2bef5e06363 100644
> --- a/drivers/gpu/drm/drm_connector.c
> +++ b/drivers/gpu/drm/drm_connector.c
> @@ -929,6 +929,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->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
> + drm_writeback_connector_cleanup(connector);
> +
> platform_device_unregister(connector->hdmi_audio.codec_pdev);
>
> if (connector->privacy_screen) {
[Severity: High]
Is every connector with connector_type == DRM_MODE_CONNECTOR_WRITEBACK
guaranteed to be embedded inside a struct drm_writeback_connector?
Unlike connector->hdmi and connector->hdmi_audio, which are fields inside
struct drm_connector itself, drm_writeback_connector_cleanup() downcasts
connector via drm_connector_to_writeback() and accesses
wb_connector->pixel_formats_blob_ptr, wb_connector->job_lock, and
wb_connector->job_queue beyond sizeof(struct drm_connector).
However, drm_connector_init(), drmm_connector_init(), and
drm_connector_dynamic_init() allow initializing a plain struct
drm_connector (or a different wrapper struct) with
DRM_MODE_CONNECTOR_WRITEBACK, and several in-tree KUnit tests do so:
1. In drivers/gpu/drm/tests/drm_connector_test.c, struct
drm_connector_init_priv places a plain struct drm_connector immediately
before struct i2c_adapter ddc:
struct drm_connector_init_priv {
struct drm_device drm;
struct drm_connector connector;
struct i2c_adapter ddc;
};
When drm_test_drmm_connector_init_type_valid() or
drm_test_drm_connector_dynamic_init_type_valid() initializes
priv->connector with DRM_MODE_CONNECTOR_WRITEBACK and later cleans it up
via drm_connector_cleanup(), wb_connector->pixel_formats_blob_ptr aliases
priv->ddc.owner (set to THIS_MODULE). When built as a module,
drm_writeback_connector_cleanup() passes THIS_MODULE to
drm_property_blob_put(), zeroes priv->ddc.owner, locks priv->ddc memory as
job_lock, and iterates job_queue over priv->ddc fields.
2. In drivers/gpu/drm/vc4/tests/vc4_mock_output.c, vc4_dummy_output()
allocates struct vc4_dummy_output (ending with a plain struct
drm_connector) and calls drmm_connector_init() with
DRM_MODE_CONNECTOR_WRITEBACK, causing drm_writeback_connector_cleanup() to
read past the end of the slab allocation.
3. In drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_audio_test.c,
dm_test_audio_component_get_eld_copies_matching_connector() allocates
sizeof(struct drm_connector) with DRM_MODE_CONNECTOR_WRITEBACK and cleans
it up via drm_connector_cleanup(), also reading out of bounds.
Could this out-of-bounds access be avoided by tracking writeback
initialization on struct drm_connector or only cleaning up when initialized
through the writeback connector helpers?
[ ... ]
> diff --git a/drivers/gpu/drm/drm_writeback.c b/drivers/gpu/drm/drm_writeback.c
> index 2f6a7b50336c0..272012a70efee 100644
> --- a/drivers/gpu/drm/drm_writeback.c
> +++ b/drivers/gpu/drm/drm_writeback.c
> @@ -271,21 +273,27 @@ 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)
> {
> - unsigned long flags;
> + struct drm_writeback_connector *wb_connector =
> + drm_connector_to_writeback(connector);
> struct drm_writeback_job *pos, *n;
> - struct drm_writeback_connector *wb_connector = data;
> + unsigned long flags;
> +
> + /* __drm_writeback_connector_init() has failed */
> + if (!wb_connector->pixel_formats_blob_ptr)
> + return;
>
> 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_for_each_entry_safe(pos, n, &wb_connector->job_queue, list_entry) {
> list_del(&pos->list_entry);
> drm_writeback_cleanup_job(pos);
> }
> spin_unlock_irqrestore(&wb_connector->job_lock, flags);
> }
[Severity: High]
Can drm_writeback_cleanup_job() be safely called while holding
wb_connector->job_lock with interrupts disabled?
When drm_connector_cleanup() tears down a writeback connector that still
has queued jobs, drm_writeback_connector_cleanup() holds
spin_lock_irqsave(&wb_connector->job_lock, flags) across
drm_writeback_cleanup_job():
drm_writeback_connector_cleanup()
spin_lock_irqsave(&wb_connector->job_lock, flags)
drm_writeback_cleanup_job()
funcs->cleanup_writeback_job()
drm_framebuffer_put()
Inside drm_writeback_cleanup_job(), dropping the final reference via
drm_framebuffer_put() calls drm_framebuffer_free() ->
drm_mode_object_unregister(), which acquires
mutex_lock(&dev->mode_config.idr_mutex), as well as
drm_framebuffer_cleanup(), which acquires
mutex_lock(&dev->object_name_lock) and
mutex_lock(&dev->mode_config.fb_lock).
In addition, hooking drm_writeback_connector_cleanup() into
drm_connector_cleanup() makes this path reachable for drivers using
drm_writeback_connector_init() such as amdgpu, where
amdgpu_dm_wb_cleanup_job() calls wb_bo_reserve() -> amdgpu_bo_reserve()
and acquires a sleeping dma_resv ww_mutex.
Should the jobs be spliced onto a local list under wb_connector->job_lock
and cleaned up after spin_unlock_irqrestore()?
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261019-wb-drop-encoder-v7-0-d4288a26eb54@oss.qualcomm.com?part=8
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v7 9/9] drm: writeback: drop the drmm writeback cleanup action
2026-10-19 13:12 [PATCH v7 0/9] drm: writeback: clean up writeback connector initialization Dmitry Baryshkov
` (7 preceding siblings ...)
2026-10-19 13:12 ` [PATCH v7 8/9] drm: writeback: clean up writeback connectors in drm_connector_cleanup() Dmitry Baryshkov
@ 2026-10-19 13:12 ` Dmitry Baryshkov
2026-10-19 19:40 ` [PATCH v7 0/9] drm: writeback: clean up writeback connector initialization John Harrison
9 siblings, 0 replies; 14+ messages in thread
From: Dmitry Baryshkov @ 2026-10-19 13:12 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
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.
Assisted-by: LLM
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 272012a70efe..0c5d2fbe7a7c 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>
@@ -303,14 +302,6 @@ void drm_writeback_connector_cleanup(struct drm_connector *connector)
spin_unlock_irqrestore(&wb_connector->job_lock, flags);
}
-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
*
@@ -321,7 +312,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
@@ -344,17 +336,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 related [flat|nested] 14+ messages in thread* Re: [PATCH v7 0/9] drm: writeback: clean up writeback connector initialization
2026-10-19 13:12 [PATCH v7 0/9] drm: writeback: clean up writeback connector initialization Dmitry Baryshkov
` (8 preceding siblings ...)
2026-10-19 13:12 ` [PATCH v7 9/9] drm: writeback: drop the drmm writeback cleanup action Dmitry Baryshkov
@ 2026-10-19 19:40 ` John Harrison
9 siblings, 0 replies; 14+ messages in thread
From: John Harrison @ 2026-10-19 19:40 UTC (permalink / raw)
To: Dmitry Baryshkov, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter, 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
On 10/19/26 06:12, Dmitry Baryshkov wrote:
> Drivers using drm_writeback_connector_init() / _with_encoder() don't
> perform cleanup in a manner similar to drmm_writeback_connector_init()
> (see drm_writeback_connector_cleanup()). Enough of the drivers don't use
> the encoder embedded into the drm_writeback connector. In preparation
> to further rework of the WB connectors (as planned to enable WB for i915
> / xe drivers, which would move drm_writeback_connector to be a field
> inside drm_connector instead of subclassing it) remove the drm_encoder
> wrapped in struct drm_writeback_connector. Rename the
> drm_writeback_connector_init_with_encoder() to
> drm_writeback_connector_init()
> and copy drmm_writeback_connector_init() interface. Then, with the
> encoder being gone, handle proper cleanup of writeback data in
> drm_connector_cleanup().
>
> ---
> Changes in v7:
> - Significantly reworked series, no longer insisting on using drmm.
Is there an intent to move everyone over to the drmm version in a future
patch set? Or is the plan to give up on that as being just too
complicated for the benefit?
John.
^ permalink raw reply [flat|nested] 14+ messages in thread