From 0e7db503c5355ff9a7471d0a450bde8c069ef803 Mon Sep 17 00:00:00 2001 From: Karol Wachowski Date: Wed, 16 Apr 2025 12:25:55 +0200 Subject: [PATCH 01/16] accel/ivpu: Implement heartbeat-based TDR mechanism Introduce a heartbeat-based Timeout Detection and Recovery (TDR) mechanism. The enhancement aims to improve the reliability of device hang detection by monitoring heartbeat updates. Each progressing inference will update heartbeat counter allowing driver to monitor its progression. Limit maximum number of reschedules when heartbeat indicates progression to 30. This increases the maximum running time of single inference to about 60 seconds. The heartbeat mechanism provides a more robust method for detecting device hangs, potentially reducing false positive recoveries due to long running inferences. Signed-off-by: Karol Wachowski Signed-off-by: Maciej Falkowski Reviewed-by: Jeff Hugo Signed-off-by: Jacek Lawrynowicz Link: https://lore.kernel.org/r/20250416102555.384526-1-maciej.falkowski@linux.intel.com --- drivers/accel/ivpu/ivpu_drv.c | 4 ++++ drivers/accel/ivpu/ivpu_drv.h | 1 + drivers/accel/ivpu/ivpu_fw.h | 1 + drivers/accel/ivpu/ivpu_pm.c | 20 ++++++++++++++++++++ 4 files changed, 26 insertions(+) diff --git a/drivers/accel/ivpu/ivpu_drv.c b/drivers/accel/ivpu/ivpu_drv.c index 4fa73189502e..392d6790b4cd 100644 --- a/drivers/accel/ivpu/ivpu_drv.c +++ b/drivers/accel/ivpu/ivpu_drv.c @@ -374,6 +374,9 @@ int ivpu_boot(struct ivpu_device *vdev) { int ret; + drm_WARN_ON(&vdev->drm, atomic_read(&vdev->job_timeout_counter)); + drm_WARN_ON(&vdev->drm, !xa_empty(&vdev->submitted_jobs_xa)); + /* Update boot params located at first 4KB of FW memory */ ivpu_fw_boot_params_setup(vdev, ivpu_bo_vaddr(vdev->fw->mem)); @@ -573,6 +576,7 @@ static int ivpu_dev_init(struct ivpu_device *vdev) vdev->context_xa_limit.min = IVPU_USER_CONTEXT_MIN_SSID; vdev->context_xa_limit.max = IVPU_USER_CONTEXT_MAX_SSID; atomic64_set(&vdev->unique_id_counter, 0); + atomic_set(&vdev->job_timeout_counter, 0); xa_init_flags(&vdev->context_xa, XA_FLAGS_ALLOC | XA_FLAGS_LOCK_IRQ); xa_init_flags(&vdev->submitted_jobs_xa, XA_FLAGS_ALLOC1); xa_init_flags(&vdev->db_xa, XA_FLAGS_ALLOC1); diff --git a/drivers/accel/ivpu/ivpu_drv.h b/drivers/accel/ivpu/ivpu_drv.h index 92753effb1c9..5497e7030e91 100644 --- a/drivers/accel/ivpu/ivpu_drv.h +++ b/drivers/accel/ivpu/ivpu_drv.h @@ -154,6 +154,7 @@ struct ivpu_device { struct mutex submitted_jobs_lock; /* Protects submitted_jobs */ struct xarray submitted_jobs_xa; struct ivpu_ipc_consumer job_done_consumer; + atomic_t job_timeout_counter; atomic64_t unique_id_counter; diff --git a/drivers/accel/ivpu/ivpu_fw.h b/drivers/accel/ivpu/ivpu_fw.h index 1d0b2bd9d65c..9a3935be1c05 100644 --- a/drivers/accel/ivpu/ivpu_fw.h +++ b/drivers/accel/ivpu/ivpu_fw.h @@ -39,6 +39,7 @@ struct ivpu_fw_info { u64 read_only_addr; u32 read_only_size; u32 sched_mode; + u64 last_heartbeat; }; int ivpu_fw_init(struct ivpu_device *vdev); diff --git a/drivers/accel/ivpu/ivpu_pm.c b/drivers/accel/ivpu/ivpu_pm.c index b5891e91f7ab..1fe03fc16bbc 100644 --- a/drivers/accel/ivpu/ivpu_pm.c +++ b/drivers/accel/ivpu/ivpu_pm.c @@ -34,6 +34,7 @@ module_param_named(tdr_timeout_ms, ivpu_tdr_timeout_ms, ulong, 0644); MODULE_PARM_DESC(tdr_timeout_ms, "Timeout for device hang detection, in milliseconds, 0 - default"); #define PM_RESCHEDULE_LIMIT 5 +#define PM_TDR_HEARTBEAT_LIMIT 30 static void ivpu_pm_prepare_cold_boot(struct ivpu_device *vdev) { @@ -44,6 +45,7 @@ static void ivpu_pm_prepare_cold_boot(struct ivpu_device *vdev) ivpu_fw_log_reset(vdev); ivpu_fw_load(vdev); fw->entry_point = fw->cold_boot_entry_point; + fw->last_heartbeat = 0; } static void ivpu_pm_prepare_warm_boot(struct ivpu_device *vdev) @@ -189,7 +191,24 @@ static void ivpu_job_timeout_work(struct work_struct *work) { struct ivpu_pm_info *pm = container_of(work, struct ivpu_pm_info, job_timeout_work.work); struct ivpu_device *vdev = pm->vdev; + u64 heartbeat; + if (ivpu_jsm_get_heartbeat(vdev, 0, &heartbeat) || heartbeat <= vdev->fw->last_heartbeat) { + ivpu_err(vdev, "Job timeout detected, heartbeat not progressed\n"); + goto recovery; + } + + if (atomic_fetch_inc(&vdev->job_timeout_counter) > PM_TDR_HEARTBEAT_LIMIT) { + ivpu_err(vdev, "Job timeout detected, heartbeat limit exceeded\n"); + goto recovery; + } + + vdev->fw->last_heartbeat = heartbeat; + ivpu_start_job_timeout_detection(vdev); + return; + +recovery: + atomic_set(&vdev->job_timeout_counter, 0); ivpu_pm_trigger_recovery(vdev, "TDR"); } @@ -204,6 +223,7 @@ void ivpu_start_job_timeout_detection(struct ivpu_device *vdev) void ivpu_stop_job_timeout_detection(struct ivpu_device *vdev) { cancel_delayed_work_sync(&vdev->pm->job_timeout_work); + atomic_set(&vdev->job_timeout_counter, 0); } int ivpu_pm_suspend_cb(struct device *dev) -- 2.51.0 From d0e4c6537005dd106b101d4434a0c3dafd936d05 Mon Sep 17 00:00:00 2001 From: Jose Maria Casanova Crespo Date: Fri, 25 Apr 2025 14:25:07 +0200 Subject: [PATCH 02/16] drm/v3d: fix client obtained from axi_ids on V3D 4.1 MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit In the case of MMU errors caused by the TFU unit, the client that causes the MMU error is expected to be reported. But in the case of MMU TFU errors, a non existing client was being reported. This happened because the client calculation was taking into account more than the bits 0-7 from the axi_id that were representing the client. [ 27.845132] v3d fec00000.v3d: MMU error from client ? (13) at 0x3bb1000, pte invalid Masking the bits and using the correct axi_id ranges fixes the calculation to report the real guilty client on V3D 4.1 and 4.2. Make the MMU error print axi_id with hexadecimal as used in the ranges. Fixes: 38c2c7917adc ("drm/v3d: Fix and extend MMU error handling.") Signed-off-by: Jose Maria Casanova Crespo Reviewed-by: Maíra Canal Link: https://lore.kernel.org/r/20250425122522.18425-1-jmcasanova@igalia.com Signed-off-by: Maíra Canal --- drivers/gpu/drm/v3d/v3d_irq.c | 37 +++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/v3d/v3d_irq.c b/drivers/gpu/drm/v3d/v3d_irq.c index 29f63f572d35..d6ce1324905d 100644 --- a/drivers/gpu/drm/v3d/v3d_irq.c +++ b/drivers/gpu/drm/v3d/v3d_irq.c @@ -186,27 +186,38 @@ v3d_hub_irq(int irq, void *arg) u32 axi_id = V3D_READ(V3D_MMU_VIO_ID); u64 vio_addr = ((u64)V3D_READ(V3D_MMU_VIO_ADDR) << (v3d->va_width - 32)); - static const char *const v3d41_axi_ids[] = { - "L2T", - "PTB", - "PSE", - "TLB", - "CLE", - "TFU", - "MMU", - "GMP", + static const struct { + u32 begin; + u32 end; + const char *client; + } v3d41_axi_ids[] = { + {0x00, 0x20, "L2T"}, + {0x20, 0x21, "PTB"}, + {0x40, 0x41, "PSE"}, + {0x60, 0x80, "TLB"}, + {0x80, 0x88, "CLE"}, + {0xA0, 0xA1, "TFU"}, + {0xC0, 0xE0, "MMU"}, + {0xE0, 0xE1, "GMP"}, }; const char *client = "?"; V3D_WRITE(V3D_MMU_CTL, V3D_READ(V3D_MMU_CTL)); if (v3d->ver >= V3D_GEN_41) { - axi_id = axi_id >> 5; - if (axi_id < ARRAY_SIZE(v3d41_axi_ids)) - client = v3d41_axi_ids[axi_id]; + size_t i; + + axi_id = axi_id & 0xFF; + for (i = 0; i < ARRAY_SIZE(v3d41_axi_ids); i++) { + if (axi_id >= v3d41_axi_ids[i].begin && + axi_id < v3d41_axi_ids[i].end) { + client = v3d41_axi_ids[i].client; + break; + } + } } - dev_err(v3d->drm.dev, "MMU error from client %s (%d) at 0x%llx%s%s%s\n", + dev_err(v3d->drm.dev, "MMU error from client %s (0x%x) at 0x%llx%s%s%s\n", client, axi_id, (long long)vio_addr, ((intsts & V3D_HUB_INT_MMU_WRV) ? ", write violation" : ""), -- 2.51.0 From a22e0051f9eb2281b181218d97f77cebc299310d Mon Sep 17 00:00:00 2001 From: Jose Maria Casanova Crespo Date: Fri, 25 Apr 2025 14:25:08 +0200 Subject: [PATCH 03/16] drm/v3d: client ranges from axi_ids are different with V3D 7.1 MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit The client mask has been reduced from 8 bits on V3D 4.1 to 7 bits on V3D 7.1, so the ranges for each client are not compatible. On V3D 7.1, the CSD client can also report MMU errors. Therefore, add its AXI ID to the IDs list. Fixes: 0ad5bc1ce463 ("drm/v3d: fix up register addresses for V3D 7.x") Signed-off-by: Jose Maria Casanova Crespo Reviewed-by: Maíra Canal Link: https://lore.kernel.org/r/20250425122522.18425-2-jmcasanova@igalia.com Signed-off-by: Maíra Canal --- drivers/gpu/drm/v3d/v3d_irq.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/v3d/v3d_irq.c b/drivers/gpu/drm/v3d/v3d_irq.c index d6ce1324905d..2cca5d3a26a2 100644 --- a/drivers/gpu/drm/v3d/v3d_irq.c +++ b/drivers/gpu/drm/v3d/v3d_irq.c @@ -199,12 +199,33 @@ v3d_hub_irq(int irq, void *arg) {0xA0, 0xA1, "TFU"}, {0xC0, 0xE0, "MMU"}, {0xE0, 0xE1, "GMP"}, + }, v3d71_axi_ids[] = { + {0x00, 0x30, "L2T"}, + {0x30, 0x38, "CLE"}, + {0x38, 0x39, "PTB"}, + {0x39, 0x3A, "PSE"}, + {0x3A, 0x3B, "CSD"}, + {0x40, 0x60, "TLB"}, + {0x60, 0x70, "MMU"}, + {0x7C, 0x7E, "TFU"}, + {0x7F, 0x80, "GMP"}, }; const char *client = "?"; V3D_WRITE(V3D_MMU_CTL, V3D_READ(V3D_MMU_CTL)); - if (v3d->ver >= V3D_GEN_41) { + if (v3d->ver >= V3D_GEN_71) { + size_t i; + + axi_id = axi_id & 0x7F; + for (i = 0; i < ARRAY_SIZE(v3d71_axi_ids); i++) { + if (axi_id >= v3d71_axi_ids[i].begin && + axi_id < v3d71_axi_ids[i].end) { + client = v3d71_axi_ids[i].client; + break; + } + } + } else if (v3d->ver >= V3D_GEN_41) { size_t i; axi_id = axi_id & 0xFF; -- 2.51.0 From d76ebdf4aa829cd05a6bc8610efbbe17d4ecc8e8 Mon Sep 17 00:00:00 2001 From: Philippe Simons Date: Thu, 3 Apr 2025 07:52:08 +0200 Subject: [PATCH 04/16] drm/panfrost: Add PM runtime flag When the GPU is the only device attached to a single power domain, core genpd disable and enable it when gpu enter and leave runtime suspend. Some power-domain requires a sequence before disabled, and the reverse when enabled. Add GPU_PM_RT flag, and implement in panfrost_device_runtime_suspend/resume. Reviewed-by: Steven Price Signed-off-by: Philippe Simons Signed-off-by: Steven Price Link: https://lore.kernel.org/r/20250403055210.54486-2-simons.philippe@gmail.com --- drivers/gpu/drm/panfrost/panfrost_device.c | 33 ++++++++++++++++++++++ drivers/gpu/drm/panfrost/panfrost_device.h | 3 ++ 2 files changed, 36 insertions(+) diff --git a/drivers/gpu/drm/panfrost/panfrost_device.c b/drivers/gpu/drm/panfrost/panfrost_device.c index a45e4addcc19..93d48e97ce10 100644 --- a/drivers/gpu/drm/panfrost/panfrost_device.c +++ b/drivers/gpu/drm/panfrost/panfrost_device.c @@ -406,11 +406,36 @@ void panfrost_device_reset(struct panfrost_device *pfdev) static int panfrost_device_runtime_resume(struct device *dev) { struct panfrost_device *pfdev = dev_get_drvdata(dev); + int ret; + + if (pfdev->comp->pm_features & BIT(GPU_PM_RT)) { + ret = reset_control_deassert(pfdev->rstc); + if (ret) + return ret; + + ret = clk_enable(pfdev->clock); + if (ret) + goto err_clk; + + if (pfdev->bus_clock) { + ret = clk_enable(pfdev->bus_clock); + if (ret) + goto err_bus_clk; + } + } panfrost_device_reset(pfdev); panfrost_devfreq_resume(pfdev); return 0; + +err_bus_clk: + if (pfdev->comp->pm_features & BIT(GPU_PM_RT)) + clk_disable(pfdev->clock); +err_clk: + if (pfdev->comp->pm_features & BIT(GPU_PM_RT)) + reset_control_assert(pfdev->rstc); + return ret; } static int panfrost_device_runtime_suspend(struct device *dev) @@ -426,6 +451,14 @@ static int panfrost_device_runtime_suspend(struct device *dev) panfrost_gpu_suspend_irq(pfdev); panfrost_gpu_power_off(pfdev); + if (pfdev->comp->pm_features & BIT(GPU_PM_RT)) { + if (pfdev->bus_clock) + clk_disable(pfdev->bus_clock); + + clk_disable(pfdev->clock); + reset_control_assert(pfdev->rstc); + } + return 0; } diff --git a/drivers/gpu/drm/panfrost/panfrost_device.h b/drivers/gpu/drm/panfrost/panfrost_device.h index ad95f2ed31d9..dcff70f905cd 100644 --- a/drivers/gpu/drm/panfrost/panfrost_device.h +++ b/drivers/gpu/drm/panfrost/panfrost_device.h @@ -36,10 +36,13 @@ enum panfrost_drv_comp_bits { * enum panfrost_gpu_pm - Supported kernel power management features * @GPU_PM_CLK_DIS: Allow disabling clocks during system suspend * @GPU_PM_VREG_OFF: Allow turning off regulators during system suspend + * @GPU_PM_RT: Allow disabling clocks and asserting the reset control during + * system runtime suspend */ enum panfrost_gpu_pm { GPU_PM_CLK_DIS, GPU_PM_VREG_OFF, + GPU_PM_RT }; /** -- 2.51.0 From 95bdaa89b29aea2a1293b63bd494498a8a41af5f Mon Sep 17 00:00:00 2001 From: Philippe Simons Date: Thu, 3 Apr 2025 07:52:09 +0200 Subject: [PATCH 05/16] drm/panfrost: add h616 compatible string Tie the Allwinner compatible string to the GPU_PM_RT feature bits that will toggle the clocks and the reset line whenever the power domain is changing state. Reviewed-by: Steven Price Signed-off-by: Philippe Simons Signed-off-by: Steven Price Link: https://lore.kernel.org/r/20250403055210.54486-3-simons.philippe@gmail.com --- drivers/gpu/drm/panfrost/panfrost_drv.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c index b87f83e94eda..f1ec3b02f15a 100644 --- a/drivers/gpu/drm/panfrost/panfrost_drv.c +++ b/drivers/gpu/drm/panfrost/panfrost_drv.c @@ -776,6 +776,13 @@ static const struct panfrost_compatible default_data = { .pm_domain_names = NULL, }; +static const struct panfrost_compatible allwinner_h616_data = { + .num_supplies = ARRAY_SIZE(default_supplies) - 1, + .supply_names = default_supplies, + .num_pm_domains = 1, + .pm_features = BIT(GPU_PM_RT), +}; + static const struct panfrost_compatible amlogic_data = { .num_supplies = ARRAY_SIZE(default_supplies) - 1, .supply_names = default_supplies, @@ -861,6 +868,7 @@ static const struct of_device_id dt_match[] = { { .compatible = "mediatek,mt8186-mali", .data = &mediatek_mt8186_data }, { .compatible = "mediatek,mt8188-mali", .data = &mediatek_mt8188_data }, { .compatible = "mediatek,mt8192-mali", .data = &mediatek_mt8192_data }, + { .compatible = "allwinner,sun50i-h616-mali", .data = &allwinner_h616_data }, {} }; MODULE_DEVICE_TABLE(of, dt_match); -- 2.51.0 From 69b8115fc8d1d57c37b003e7c39a927c5b03390e Mon Sep 17 00:00:00 2001 From: Philippe Simons Date: Thu, 3 Apr 2025 07:52:10 +0200 Subject: [PATCH 06/16] drm/panfrost: reorder pd/clk/rst sequence According to Mali manuals, the powerup sequence should be enable pd, asserting the reset then enabling the clock and the reverse for powerdown. Reviewed-by: Steven Price Tested-by: John Williams Signed-off-by: Philippe Simons Signed-off-by: Steven Price Link: https://lore.kernel.org/r/20250403055210.54486-4-simons.philippe@gmail.com --- drivers/gpu/drm/panfrost/panfrost_device.c | 38 +++++++++++----------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/panfrost/panfrost_device.c b/drivers/gpu/drm/panfrost/panfrost_device.c index 93d48e97ce10..5d35076b2e6d 100644 --- a/drivers/gpu/drm/panfrost/panfrost_device.c +++ b/drivers/gpu/drm/panfrost/panfrost_device.c @@ -209,10 +209,20 @@ int panfrost_device_init(struct panfrost_device *pfdev) spin_lock_init(&pfdev->cycle_counter.lock); + err = panfrost_pm_domain_init(pfdev); + if (err) + return err; + + err = panfrost_reset_init(pfdev); + if (err) { + dev_err(pfdev->dev, "reset init failed %d\n", err); + goto out_pm_domain; + } + err = panfrost_clk_init(pfdev); if (err) { dev_err(pfdev->dev, "clk init failed %d\n", err); - return err; + goto out_reset; } err = panfrost_devfreq_init(pfdev); @@ -229,25 +239,15 @@ int panfrost_device_init(struct panfrost_device *pfdev) goto out_devfreq; } - err = panfrost_reset_init(pfdev); - if (err) { - dev_err(pfdev->dev, "reset init failed %d\n", err); - goto out_regulator; - } - - err = panfrost_pm_domain_init(pfdev); - if (err) - goto out_reset; - pfdev->iomem = devm_platform_ioremap_resource(pfdev->pdev, 0); if (IS_ERR(pfdev->iomem)) { err = PTR_ERR(pfdev->iomem); - goto out_pm_domain; + goto out_regulator; } err = panfrost_gpu_init(pfdev); if (err) - goto out_pm_domain; + goto out_regulator; err = panfrost_mmu_init(pfdev); if (err) @@ -268,16 +268,16 @@ out_mmu: panfrost_mmu_fini(pfdev); out_gpu: panfrost_gpu_fini(pfdev); -out_pm_domain: - panfrost_pm_domain_fini(pfdev); -out_reset: - panfrost_reset_fini(pfdev); out_regulator: panfrost_regulator_fini(pfdev); out_devfreq: panfrost_devfreq_fini(pfdev); out_clk: panfrost_clk_fini(pfdev); +out_reset: + panfrost_reset_fini(pfdev); +out_pm_domain: + panfrost_pm_domain_fini(pfdev); return err; } @@ -287,11 +287,11 @@ void panfrost_device_fini(struct panfrost_device *pfdev) panfrost_job_fini(pfdev); panfrost_mmu_fini(pfdev); panfrost_gpu_fini(pfdev); - panfrost_pm_domain_fini(pfdev); - panfrost_reset_fini(pfdev); panfrost_devfreq_fini(pfdev); panfrost_regulator_fini(pfdev); panfrost_clk_fini(pfdev); + panfrost_reset_fini(pfdev); + panfrost_pm_domain_fini(pfdev); } #define PANFROST_EXCEPTION(id) \ -- 2.51.0 From 411465d35bc56877c33e2498ac697acfcf484e6b Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Thu, 24 Apr 2025 20:59:09 +0200 Subject: [PATCH 07/16] platform: arm64: acer-aspire1-ec: convert to devm_drm_bridge_alloc() API MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This is the new API for allocating DRM bridges. Acked-by: Ilpo Järvinen Signed-off-by: Luca Ceresoli Link: https://patchwork.freedesktop.org/patch/msgid/20250424-drm-bridge-convert-to-alloc-api-v2-2-8f91a404d86b@bootlin.com Signed-off-by: Louis Chauvet --- drivers/platform/arm64/acer-aspire1-ec.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/platform/arm64/acer-aspire1-ec.c b/drivers/platform/arm64/acer-aspire1-ec.c index 958fe1bf5f85..438532a047e6 100644 --- a/drivers/platform/arm64/acer-aspire1-ec.c +++ b/drivers/platform/arm64/acer-aspire1-ec.c @@ -452,9 +452,9 @@ static int aspire_ec_probe(struct i2c_client *client) int ret; u8 tmp; - ec = devm_kzalloc(dev, sizeof(*ec), GFP_KERNEL); - if (!ec) - return -ENOMEM; + ec = devm_drm_bridge_alloc(dev, struct aspire_ec, bridge, &aspire_ec_bridge_funcs); + if (IS_ERR(ec)) + return PTR_ERR(ec); ec->client = client; i2c_set_clientdata(client, ec); @@ -497,7 +497,6 @@ static int aspire_ec_probe(struct i2c_client *client) fwnode = device_get_named_child_node(dev, "connector"); if (fwnode) { INIT_WORK(&ec->work, aspire_ec_bridge_update_hpd_work); - ec->bridge.funcs = &aspire_ec_bridge_funcs; ec->bridge.of_node = to_of_node(fwnode); ec->bridge.ops = DRM_BRIDGE_OP_HPD; ec->bridge.type = DRM_MODE_CONNECTOR_USB; -- 2.51.0 From 53ddeb25159781b029fda404226af600e76f975f Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Thu, 24 Apr 2025 20:59:10 +0200 Subject: [PATCH 08/16] drm/bridge: analogix-anx6345: convert to devm_drm_bridge_alloc() API This is the new API for allocating DRM bridges. Signed-off-by: Luca Ceresoli Reviewed-by: Andy Yan Link: https://patchwork.freedesktop.org/patch/msgid/20250424-drm-bridge-convert-to-alloc-api-v2-3-8f91a404d86b@bootlin.com Signed-off-by: Louis Chauvet --- drivers/gpu/drm/bridge/analogix/analogix-anx6345.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c b/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c index f2bafa6cf779..f3fe47b12edc 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c +++ b/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c @@ -664,9 +664,10 @@ static int anx6345_i2c_probe(struct i2c_client *client) struct device *dev; int i, err; - anx6345 = devm_kzalloc(&client->dev, sizeof(*anx6345), GFP_KERNEL); - if (!anx6345) - return -ENOMEM; + anx6345 = devm_drm_bridge_alloc(&client->dev, struct anx6345, bridge, + &anx6345_bridge_funcs); + if (IS_ERR(anx6345)) + return PTR_ERR(anx6345); mutex_init(&anx6345->lock); @@ -738,7 +739,6 @@ static int anx6345_i2c_probe(struct i2c_client *client) /* Look for supported chip ID */ anx6345_poweron(anx6345); if (anx6345_get_chip_id(anx6345)) { - anx6345->bridge.funcs = &anx6345_bridge_funcs; drm_bridge_add(&anx6345->bridge); return 0; -- 2.51.0 From 4e90a3d96a6185e143041273f9867a1092dd4a71 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Thu, 24 Apr 2025 20:59:13 +0200 Subject: [PATCH 09/16] drm/bridge: display-connector: convert to devm_drm_bridge_alloc() API This is the new API for allocating DRM bridges. Reviewed-by: Dmitry Baryshkov Signed-off-by: Luca Ceresoli Link: https://patchwork.freedesktop.org/patch/msgid/20250424-drm-bridge-convert-to-alloc-api-v2-6-8f91a404d86b@bootlin.com Signed-off-by: Louis Chauvet --- drivers/gpu/drm/bridge/display-connector.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/bridge/display-connector.c b/drivers/gpu/drm/bridge/display-connector.c index 09c08a53d5bd..badd2c7f91a1 100644 --- a/drivers/gpu/drm/bridge/display-connector.c +++ b/drivers/gpu/drm/bridge/display-connector.c @@ -210,9 +210,10 @@ static int display_connector_probe(struct platform_device *pdev) const char *label = NULL; int ret; - conn = devm_kzalloc(&pdev->dev, sizeof(*conn), GFP_KERNEL); - if (!conn) - return -ENOMEM; + conn = devm_drm_bridge_alloc(&pdev->dev, struct display_connector, bridge, + &display_connector_bridge_funcs); + if (IS_ERR(conn)) + return PTR_ERR(conn); platform_set_drvdata(pdev, conn); @@ -362,7 +363,6 @@ static int display_connector_probe(struct platform_device *pdev) } } - conn->bridge.funcs = &display_connector_bridge_funcs; conn->bridge.of_node = pdev->dev.of_node; if (conn->bridge.ddc) -- 2.51.0 From 6287ffd9eff6eea65865e64b9d4c45e115fa5ecf Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Thu, 24 Apr 2025 20:59:14 +0200 Subject: [PATCH 10/16] drm/bridge: lt9611uxc: convert to devm_drm_bridge_alloc() API This is the new API for allocating DRM bridges. Reviewed-by: Dmitry Baryshkov Signed-off-by: Luca Ceresoli Link: https://patchwork.freedesktop.org/patch/msgid/20250424-drm-bridge-convert-to-alloc-api-v2-7-8f91a404d86b@bootlin.com Signed-off-by: Louis Chauvet --- drivers/gpu/drm/bridge/lontium-lt9611uxc.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c index bb33c30d3f88..766da2cb45a7 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c +++ b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c @@ -775,9 +775,9 @@ static int lt9611uxc_probe(struct i2c_client *client) return -ENODEV; } - lt9611uxc = devm_kzalloc(dev, sizeof(*lt9611uxc), GFP_KERNEL); - if (!lt9611uxc) - return -ENOMEM; + lt9611uxc = devm_drm_bridge_alloc(dev, struct lt9611uxc, bridge, <9611uxc_bridge_funcs); + if (IS_ERR(lt9611uxc)) + return PTR_ERR(lt9611uxc); lt9611uxc->dev = dev; lt9611uxc->client = client; @@ -856,7 +856,6 @@ retry: i2c_set_clientdata(client, lt9611uxc); - lt9611uxc->bridge.funcs = <9611uxc_bridge_funcs; lt9611uxc->bridge.of_node = client->dev.of_node; lt9611uxc->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID; if (lt9611uxc->hpd_supported) -- 2.51.0 From ed6987b674185873ebed7a619a646da6dd1a78fa Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Thu, 24 Apr 2025 20:59:18 +0200 Subject: [PATCH 11/16] drm/bridge: dw-hdmi: convert to devm_drm_bridge_alloc() API This is the new API for allocating DRM bridges. Signed-off-by: Luca Ceresoli Reviewed-by: Cristian Ciocaltea Link: https://patchwork.freedesktop.org/patch/msgid/20250424-drm-bridge-convert-to-alloc-api-v2-11-8f91a404d86b@bootlin.com Signed-off-by: Louis Chauvet --- drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index deaba3b6f997..8791408dd1ff 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -3333,9 +3333,9 @@ struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev, u8 config0; u8 config3; - hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL); - if (!hdmi) - return ERR_PTR(-ENOMEM); + hdmi = devm_drm_bridge_alloc(dev, struct dw_hdmi, bridge, &dw_hdmi_bridge_funcs); + if (IS_ERR(hdmi)) + return hdmi; hdmi->plat_data = plat_data; hdmi->dev = dev; @@ -3495,7 +3495,6 @@ struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev, } hdmi->bridge.driver_private = hdmi; - hdmi->bridge.funcs = &dw_hdmi_bridge_funcs; hdmi->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_HPD; hdmi->bridge.interlace_allowed = true; -- 2.51.0 From 7fe58bf1a9a24b533875c262a3222581a3f759e4 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Thu, 24 Apr 2025 20:59:19 +0200 Subject: [PATCH 12/16] drm/bridge: tda998x: convert to devm_drm_bridge_alloc() API This is the new API for allocating DRM bridges. Reviewed-by: Dmitry Baryshkov Signed-off-by: Luca Ceresoli Link: https://patchwork.freedesktop.org/patch/msgid/20250424-drm-bridge-convert-to-alloc-api-v2-12-8f91a404d86b@bootlin.com Signed-off-by: Louis Chauvet --- drivers/gpu/drm/bridge/tda998x_drv.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/bridge/tda998x_drv.c b/drivers/gpu/drm/bridge/tda998x_drv.c index ac87033ba537..850909f78a7b 100644 --- a/drivers/gpu/drm/bridge/tda998x_drv.c +++ b/drivers/gpu/drm/bridge/tda998x_drv.c @@ -1781,9 +1781,9 @@ static int tda998x_create(struct device *dev) u32 video; int rev_lo, rev_hi, ret; - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; + priv = devm_drm_bridge_alloc(dev, struct tda998x_priv, bridge, &tda998x_bridge_funcs); + if (IS_ERR(priv)) + return PTR_ERR(priv); dev_set_drvdata(dev, priv); @@ -1948,7 +1948,6 @@ static int tda998x_create(struct device *dev) tda998x_audio_codec_init(priv, &client->dev); } - priv->bridge.funcs = &tda998x_bridge_funcs; #ifdef CONFIG_OF priv->bridge.of_node = dev->of_node; #endif -- 2.51.0 From a4754ae9cfa76fbce79f023c268a5bac56f36321 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Thu, 24 Apr 2025 20:59:20 +0200 Subject: [PATCH 13/16] drm/bridge: ti-sn65dsi86: convert to devm_drm_bridge_alloc() API This is the new API for allocating DRM bridges. Reviewed-by: Herve Codina Signed-off-by: Luca Ceresoli Reviewed-by: Douglas Anderson Tested-by: Douglas Anderson Link: https://patchwork.freedesktop.org/patch/msgid/20250424-drm-bridge-convert-to-alloc-api-v2-13-8f91a404d86b@bootlin.com Signed-off-by: Louis Chauvet --- drivers/gpu/drm/bridge/ti-sn65dsi86.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c index f72675766e01..60224f476e1d 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c @@ -1317,7 +1317,6 @@ static int ti_sn_bridge_probe(struct auxiliary_device *adev, if (ret) return ret; - pdata->bridge.funcs = &ti_sn_bridge_funcs; pdata->bridge.of_node = np; pdata->bridge.type = pdata->next_bridge->type == DRM_MODE_CONNECTOR_DisplayPort ? DRM_MODE_CONNECTOR_DisplayPort : DRM_MODE_CONNECTOR_eDP; @@ -1907,9 +1906,9 @@ static int ti_sn65dsi86_probe(struct i2c_client *client) return -ENODEV; } - pdata = devm_kzalloc(dev, sizeof(struct ti_sn65dsi86), GFP_KERNEL); - if (!pdata) - return -ENOMEM; + pdata = devm_drm_bridge_alloc(dev, struct ti_sn65dsi86, bridge, &ti_sn_bridge_funcs); + if (IS_ERR(pdata)) + return PTR_ERR(pdata); dev_set_drvdata(dev, pdata); pdata->dev = dev; -- 2.51.0 From 91c5c7b5bb2dd09b43b025bce6d790d3c79f4518 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Thu, 24 Apr 2025 20:59:21 +0200 Subject: [PATCH 14/16] drm/exynos: mic: convert to devm_drm_bridge_alloc() API This is the new API for allocating DRM bridges. Signed-off-by: Luca Ceresoli Link: https://patchwork.freedesktop.org/patch/msgid/20250424-drm-bridge-convert-to-alloc-api-v2-14-8f91a404d86b@bootlin.com Signed-off-by: Louis Chauvet --- drivers/gpu/drm/exynos/exynos_drm_mic.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_mic.c b/drivers/gpu/drm/exynos/exynos_drm_mic.c index b34ec6728337..29a8366513fa 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_mic.c +++ b/drivers/gpu/drm/exynos/exynos_drm_mic.c @@ -379,11 +379,11 @@ static int exynos_mic_probe(struct platform_device *pdev) struct resource res; int ret, i; - mic = devm_kzalloc(dev, sizeof(*mic), GFP_KERNEL); - if (!mic) { + mic = devm_drm_bridge_alloc(dev, struct exynos_mic, bridge, &mic_bridge_funcs); + if (IS_ERR(mic)) { DRM_DEV_ERROR(dev, "mic: Failed to allocate memory for MIC object\n"); - ret = -ENOMEM; + ret = PTR_ERR(mic); goto err; } @@ -421,7 +421,6 @@ static int exynos_mic_probe(struct platform_device *pdev) platform_set_drvdata(pdev, mic); - mic->bridge.funcs = &mic_bridge_funcs; mic->bridge.of_node = dev->of_node; drm_bridge_add(&mic->bridge); -- 2.51.0 From 40c25b9ec641f43ba17c7b788ac16ec23f8daaa8 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Thu, 24 Apr 2025 20:59:22 +0200 Subject: [PATCH 15/16] drm/mcde: convert to devm_drm_bridge_alloc() API This is the new API for allocating DRM bridges. Signed-off-by: Luca Ceresoli Reviewed-by: Linus Walleij Link: https://patchwork.freedesktop.org/patch/msgid/20250424-drm-bridge-convert-to-alloc-api-v2-15-8f91a404d86b@bootlin.com Signed-off-by: Louis Chauvet --- drivers/gpu/drm/mcde/mcde_dsi.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/mcde/mcde_dsi.c b/drivers/gpu/drm/mcde/mcde_dsi.c index b302d8ec3ad0..a3423459dd7a 100644 --- a/drivers/gpu/drm/mcde/mcde_dsi.c +++ b/drivers/gpu/drm/mcde/mcde_dsi.c @@ -1138,7 +1138,6 @@ static int mcde_dsi_bind(struct device *dev, struct device *master, d->bridge_out = bridge; /* Create a bridge for this DSI channel */ - d->bridge.funcs = &mcde_dsi_bridge_funcs; d->bridge.of_node = dev->of_node; drm_bridge_add(&d->bridge); @@ -1174,9 +1173,9 @@ static int mcde_dsi_probe(struct platform_device *pdev) u32 dsi_id; int ret; - d = devm_kzalloc(dev, sizeof(*d), GFP_KERNEL); - if (!d) - return -ENOMEM; + d = devm_drm_bridge_alloc(dev, struct mcde_dsi, bridge, &mcde_dsi_bridge_funcs); + if (IS_ERR(d)) + return PTR_ERR(d); d->dev = dev; platform_set_drvdata(pdev, d); -- 2.51.0 From b2aabe5c6b65516d88214aba4b12ce2ca78bac6c Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Thu, 24 Apr 2025 20:59:23 +0200 Subject: [PATCH 16/16] drm/msm/dp: convert to devm_drm_bridge_alloc() API This is the new API for allocating DRM bridges. Reviewed-by: Dmitry Baryshkov Signed-off-by: Luca Ceresoli Link: https://patchwork.freedesktop.org/patch/msgid/20250424-drm-bridge-convert-to-alloc-api-v2-16-8f91a404d86b@bootlin.com Signed-off-by: Louis Chauvet --- drivers/gpu/drm/msm/dp/dp_drm.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c index cca57e56c906..293f4745f1e2 100644 --- a/drivers/gpu/drm/msm/dp/dp_drm.c +++ b/drivers/gpu/drm/msm/dp/dp_drm.c @@ -296,14 +296,15 @@ int msm_dp_bridge_init(struct msm_dp *msm_dp_display, struct drm_device *dev, struct msm_dp_bridge *msm_dp_bridge; struct drm_bridge *bridge; - msm_dp_bridge = devm_kzalloc(dev->dev, sizeof(*msm_dp_bridge), GFP_KERNEL); - if (!msm_dp_bridge) - return -ENOMEM; + msm_dp_bridge = devm_drm_bridge_alloc(dev->dev, struct msm_dp_bridge, bridge, + msm_dp_display->is_edp ? &msm_edp_bridge_ops : + &msm_dp_bridge_ops); + if (IS_ERR(msm_dp_bridge)) + return PTR_ERR(msm_dp_bridge); msm_dp_bridge->msm_dp_display = msm_dp_display; bridge = &msm_dp_bridge->bridge; - bridge->funcs = msm_dp_display->is_edp ? &msm_edp_bridge_ops : &msm_dp_bridge_ops; bridge->type = msm_dp_display->connector_type; bridge->ycbcr_420_allowed = yuv_supported; -- 2.51.0