Re: [PATCH 3/5] accel/qaic: Add consistent integer overflow checks
On 7/8/2023 12:21 AM, Jeffrey Hugo wrote: On 6/21/2023 1:22 AM, Dan Carpenter wrote: The encode_dma() function has integer overflow checks. The encode_passthrough(), encode_activate() and encode_status() functions did not. I added integer overflow checking everywhere. I also updated the integer overflow checking in encode_dma() to use size_add() so everything is consistent. Fixes: 129776ac2e38 ("accel/qaic: Add control path") Signed-off-by: Dan Carpenter Reviewed-by: Jeffrey Hugo Looks good to me. Just the #include as Jeff suggested. Reviewed-by: Pranjal Ramajor Asha Kanojiya
Re: [PATCH 5/5] accel/qaic: Fix a leak in map_user_pages()
On 6/21/2023 12:52 PM, Dan Carpenter wrote: If get_user_pages_fast() allocates some pages but not as many as we wanted, then the current code leaks those pages. Call put_page() on the pages before returning. Fixes: 129776ac2e38 ("accel/qaic: Add control path") Signed-off-by: Dan Carpenter --- drivers/accel/qaic/qaic_control.c | 7 +-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/accel/qaic/qaic_control.c b/drivers/accel/qaic/qaic_control.c index 03932197f1ac..7c3f9009617f 100644 --- a/drivers/accel/qaic/qaic_control.c +++ b/drivers/accel/qaic/qaic_control.c @@ -424,9 +424,12 @@ static int find_and_map_user_pages(struct qaic_device *qdev, } ret = get_user_pages_fast(xfer_start_addr, nr_pages, 0, page_list); - if (ret < 0 || ret != nr_pages) { - ret = -EFAULT; + if (ret < 0) goto free_page_list; + if (ret != nr_pages) { + nr_pages = ret; + ret = -EFAULT; + goto put_pages; } sgt = kmalloc(sizeof(*sgt), GFP_KERNEL); Thank you for catching this :) Reviewed-by: Pranjal Ramajor Asha Kanojiya
Re: [PATCH 2/2] drm/msm/dpu: fix DSC 1.2 enc subblock length
On 6/22/2023 6:37 PM, Dmitry Baryshkov wrote: Both struct dpu_dsc_sub_blks instances declare enc subblock length to be 0x100, while the actual length is 0x9c (last register having offset 0x98). Reduce subblock length to remove the empty register space from being dumped. Fixes: 0d1b10c63346 ("drm/msm/dpu: add DSC 1.2 hw blocks for relevant chipsets") Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) Reviewed-by: Abhinav Kumar
Re: [PATCH v5 0/6] Add support to print sub-block registers in dpu hw catalog
On 7/7/2023 6:24 PM, Ryan McCann wrote: The purpose of this patch series is to add support to print the registers of sub-blocks in the DPU hardware catalog and fix the order in which all hardware blocks are dumped for a device core dump. This involves: Nice work on completing this feature and working patiently through all the comments ! 1. Changing data structure from stack to queue to fix the printing order of the device core dump. 2. Removing redundant suffix of sub-block names. 3. Removing redundant prefix of sub-block names. 4. Eliminating unused variable from relevant macros. 5. Defining names for sub-blocks that have not yet been defined. 6. Implementing wrapper function that prints the registers of sub-blocks when there is a need. Sample Output of the sspp_0 block and its sub-blocks for devcore dump: ==sspp_0== ...registers ... sspp_0_scaler ... ... sspp_0_csc ... ... next_block ... This series depends on https://patchwork.freedesktop.org/series/119776/. --- Changes in v5: - Fixed indentation in refactor main block printing patch - Fixed formatting issues to satisfy checkpatch - Instead of passing 0 for DSC block, used actual length thanks to https://patchwork.freedesktop.org/series/119776/ - Link to v4: https://lore.kernel.org/r/20230622-devcoredump_patch-v4-0-e304ddbe9...@quicinc.com Changes in v4: - Added review tags - Link to v3: https://lore.kernel.org/r/20230622-devcoredump_patch-v3-0-83601b72e...@quicinc.com Changes in v3: - Split sub-block changes and main block changes into two commits - Corrected typo in comment located in DSC for loop block - Eliminated variables mmio and base - Dropped unnecessary "%s" - Link to v2: https://lore.kernel.org/r/20230622-devcoredump_patch-v2-0-9e90a87d3...@quicinc.com Changes in v2: - Changed spelling "sub block" to "sub-block" or "sblk". - Capitalized DPU. - Eliminated multiplexer/wrapper function. Inlined instead. - Changed if statements from feature checks to length checks. - Squashed prefix and suffix patch into one. - Link to v1: https://lore.kernel.org/r/20230622-devcoredump_patch-v1-0-3b2cdcc6a...@quicinc.com --- Ryan McCann (6): drm/msm: Update dev core dump to not print backwards drm/msm/dpu: Drop unused num argument from relevant macros drm/msm/dpu: Define names for unnamed sblks drm/msm/dpu: Remove redundant prefix/suffix in name of sub-blocks drm/msm/dpu: Refactor printing of main blocks in device core dump drm/msm/dpu: Update dev core dump to dump registers of sub-blocks drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c| 90 +++ drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 74 +++ drivers/gpu/drm/msm/disp/msm_disp_snapshot_util.c | 2 +- 3 files changed, 104 insertions(+), 62 deletions(-) --- base-commit: a92b5625851098af521cd92e4c518429b661c8f4 change-id: 20230622-devcoredump_patch-df7e8f6fd632 Best regards,
Re: [PATCH v5 6/6] drm/msm/dpu: Update dev core dump to dump registers of sub-blocks
On 7/7/2023 6:24 PM, Ryan McCann wrote: Currently, the device core dump mechanism does not dump registers of sub-blocks within the DSPP, SSPP, DSC, and PINGPONG blocks. Edit dpu_kms_mdp_snapshot function to account for sub-blocks. Signed-off-by: Ryan McCann --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 66 +++-- 1 file changed, 54 insertions(+), 12 deletions(-) Overall, I like this one. Reviewed-by: Abhinav Kumar
Re: [PATCH v5 6/6] drm/msm/dpu: Update dev core dump to dump registers of sub-blocks
On 08/07/2023 04:24, Ryan McCann wrote: Currently, the device core dump mechanism does not dump registers of sub-blocks within the DSPP, SSPP, DSC, and PINGPONG blocks. Edit dpu_kms_mdp_snapshot function to account for sub-blocks. Signed-off-by: Ryan McCann --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 66 +++-- 1 file changed, 54 insertions(+), 12 deletions(-) Reviewed-by: Dmitry Baryshkov diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index 7a2787279ba0..f7199a5c45ab 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -890,6 +890,7 @@ static void dpu_kms_mdp_snapshot(struct msm_disp_state *disp_state, struct msm_k int i; struct dpu_kms *dpu_kms; const struct dpu_mdss_cfg *cat; + void __iomem *base; dpu_kms = to_dpu_kms(kms); @@ -903,9 +904,16 @@ static void dpu_kms_mdp_snapshot(struct msm_disp_state *disp_state, struct msm_k dpu_kms->mmio + cat->ctl[i].base, cat->ctl[i].name); /* dump DSPP sub-blocks HW regs info */ - for (i = 0; i < cat->dspp_count; i++) - msm_disp_snapshot_add_block(disp_state, cat->dspp[i].len, - dpu_kms->mmio + cat->dspp[i].base, cat->dspp[i].name); + for (i = 0; i < cat->dspp_count; i++) { + base = dpu_kms->mmio + cat->dspp[i].base; + msm_disp_snapshot_add_block(disp_state, cat->dspp[i].len, base, cat->dspp[i].name); + + if (cat->dspp[i].sblk && cat->dspp[i].sblk->pcc.len > 0) + msm_disp_snapshot_add_block(disp_state, cat->dspp[i].sblk->pcc.len, + base + cat->dspp[i].sblk->pcc.base, "%s_%s", + cat->dspp[i].name, + cat->dspp[i].sblk->pcc.name); Nit (no need to resend to correct this): the "%s_%s" logically fits the next line, as it it related to the names rather than base address. + } /* dump INTF sub-blocks HW regs info */ for (i = 0; i < cat->intf_count; i++) -- With best wishes Dmitry
Re: [PATCH v5 5/6] drm/msm/dpu: Refactor printing of main blocks in device core dump
On 08/07/2023 04:24, Ryan McCann wrote: Currently, the names of main blocks are hardcoded into the msm_disp_snapshot_add_block function rather than using the name that already exists in the catalog. Change this to take the name directly from the catalog instead of hardcoding it. Signed-off-by: Ryan McCann --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 16 1 file changed, 8 insertions(+), 8 deletions(-) Reviewed-by: Dmitry Baryshkov -- With best wishes Dmitry
Re: [PATCH v5 5/6] drm/msm/dpu: Refactor printing of main blocks in device core dump
On 7/7/2023 6:24 PM, Ryan McCann wrote: Currently, the names of main blocks are hardcoded into the msm_disp_snapshot_add_block function rather than using the name that already exists in the catalog. Change this to take the name directly from the catalog instead of hardcoding it. Signed-off-by: Ryan McCann --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 16 1 file changed, 8 insertions(+), 8 deletions(-) Reviewed-by: Abhinav Kumar
[PATCH v5 4/6] drm/msm/dpu: Remove redundant prefix/suffix in name of sub-blocks
For a device core dump, the registers of sub-blocks are printed under a title formatted as . For example, the csc sub-block for an SSPP main block "sspp_0" would be printed "sspp_0_sspp_csc0". The title is clearly redundant due to the duplicate "sspp" and "0" that exist in both the mainBlkName and sblkName. To eliminate this redundancy, remove the secondary "sspp" and "0" that exist in the sub-block name by elimanting the "sspp_" prefix and the concatenation of "num" that results in the redundant "0" suffix. Remove num parameter altogether from relevant macros as a consequence of it no longer being used. Reviewed-by: Abhinav Kumar Reviewed-by: Dmitry Baryshkov Signed-off-by: Ryan McCann --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 50 +- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c index e2879cc84ee0..2a903ab29964 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -252,15 +252,15 @@ static const uint32_t wb2_formats[] = { */ /* SSPP common configuration */ -#define _VIG_SBLK(num, sdma_pri, qseed_ver) \ +#define _VIG_SBLK(sdma_pri, qseed_ver) \ { \ .maxdwnscale = MAX_DOWNSCALE_RATIO, \ .maxupscale = MAX_UPSCALE_RATIO, \ .smart_dma_priority = sdma_pri, \ - .scaler_blk = {.name = STRCAT("sspp_scaler", num), \ + .scaler_blk = {.name = "scaler", \ .id = qseed_ver, \ .base = 0xa00, .len = 0xa0,}, \ - .csc_blk = {.name = STRCAT("sspp_csc", num), \ + .csc_blk = {.name = "csc", \ .id = DPU_SSPP_CSC_10BIT, \ .base = 0x1a00, .len = 0x100,}, \ .format_list = plane_formats_yuv, \ @@ -270,15 +270,15 @@ static const uint32_t wb2_formats[] = { .rotation_cfg = NULL, \ } -#define _VIG_SBLK_ROT(num, sdma_pri, qseed_ver, rot_cfg) \ +#define _VIG_SBLK_ROT(sdma_pri, qseed_ver, rot_cfg) \ { \ .maxdwnscale = MAX_DOWNSCALE_RATIO, \ .maxupscale = MAX_UPSCALE_RATIO, \ .smart_dma_priority = sdma_pri, \ - .scaler_blk = {.name = STRCAT("sspp_scaler", num), \ + .scaler_blk = {.name = "scaler", \ .id = qseed_ver, \ .base = 0xa00, .len = 0xa0,}, \ - .csc_blk = {.name = STRCAT("sspp_csc", num), \ + .csc_blk = {.name = "csc", \ .id = DPU_SSPP_CSC_10BIT, \ .base = 0x1a00, .len = 0x100,}, \ .format_list = plane_formats_yuv, \ @@ -300,13 +300,13 @@ static const uint32_t wb2_formats[] = { } static const struct dpu_sspp_sub_blks msm8998_vig_sblk_0 = - _VIG_SBLK("0", 0, DPU_SSPP_SCALER_QSEED3); + _VIG_SBLK(0, DPU_SSPP_SCALER_QSEED3); static const struct dpu_sspp_sub_blks msm8998_vig_sblk_1 = - _VIG_SBLK("1", 0, DPU_SSPP_SCALER_QSEED3); + _VIG_SBLK(0, DPU_SSPP_SCALER_QSEED3); static const struct dpu_sspp_sub_blks msm8998_vig_sblk_2 = - _VIG_SBLK("2", 0, DPU_SSPP_SCALER_QSEED3); + _VIG_SBLK(0, DPU_SSPP_SCALER_QSEED3); static const struct dpu_sspp_sub_blks msm8998_vig_sblk_3 = - _VIG_SBLK("3", 0, DPU_SSPP_SCALER_QSEED3); + _VIG_SBLK(0, DPU_SSPP_SCALER_QSEED3); static const struct dpu_rotation_cfg dpu_rot_sc7280_cfg_v2 = { .rot_maxheight = 1088, @@ -315,13 +315,13 @@ static const struct dpu_rotation_cfg dpu_rot_sc7280_cfg_v2 = { }; static const struct dpu_sspp_sub_blks sdm845_vig_sblk_0 = - _VIG_SBLK("0", 5, DPU_SSPP_SCALER_QSEED3); + _VIG_SBLK(5, DPU_SSPP_SCALER_QSEED3); static const struct dpu_sspp_sub_blks sdm845_vig_sblk_1 = - _VIG_SBLK("1", 6, DPU_SSPP_SCALER_QSEED3); + _VIG_SBLK(6, DPU_SSPP_SCALER_QSEED3); static const struct dpu_sspp_sub_blks sdm845_vig_sblk_2 = - _VIG_SBLK("2", 7, DPU_SSPP_SCALER_QSEED3); + _VIG_SBLK(7, DPU_SSPP_SCALER_QSEED3); static const struct dpu_sspp_sub_blks sdm845_vig_sblk_3 = - _VIG_SBLK("3", 8, DPU_SSPP_SCALER_QSEED3); + _VIG_SBLK(8, DPU_SSPP_SCALER_QSEED3); static const struct dpu_sspp_sub_blks sdm845_dma_sblk_0 = _DMA_SBLK(1); static const struct dpu_sspp_sub_blks sdm845_dma_sblk_1 = _DMA_SBLK(2); @@ -341,31 +341,31 @@ static const struct dpu_sspp_sub_blks sdm845_dma_sblk_3 = _DMA_SBLK(4); } static const struct dpu_sspp_sub_blks sc7180_vig_sblk_0 = - _VIG_SBLK("0", 4, DPU_SSPP_SCALER_QSEED4); +
[PATCH v5 1/6] drm/msm: Update dev core dump to not print backwards
Device core dump add block method adds hardware blocks to dumping queue with stack behavior which causes the hardware blocks to be printed in reverse order. Change the addition to dumping queue data structure from "list_add" to "list_add_tail" for FIFO queue behavior. Fixes: 98659487b845 ("drm/msm: add support to take dpu snapshot") Reviewed-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Signed-off-by: Ryan McCann --- drivers/gpu/drm/msm/disp/msm_disp_snapshot_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/disp/msm_disp_snapshot_util.c b/drivers/gpu/drm/msm/disp/msm_disp_snapshot_util.c index acfe1b31e079..add72bbc28b1 100644 --- a/drivers/gpu/drm/msm/disp/msm_disp_snapshot_util.c +++ b/drivers/gpu/drm/msm/disp/msm_disp_snapshot_util.c @@ -192,5 +192,5 @@ void msm_disp_snapshot_add_block(struct msm_disp_state *disp_state, u32 len, new_blk->base_addr = base_addr; msm_disp_state_dump_regs(_blk->state, new_blk->size, base_addr); - list_add(_blk->node, _state->blocks); + list_add_tail(_blk->node, _state->blocks); } -- 2.25.1
[PATCH v5 3/6] drm/msm/dpu: Define names for unnamed sblks
Some sub-blocks in the hw catalog have not been given a name, so when the registers from that block are dumped, there is no name to reference. Define names for relevant sub-blocks to fix this. Reviewed-by: Abhinav Kumar Reviewed-by: Dmitry Baryshkov Signed-off-by: Ryan McCann --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 20 ++-- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c index 1291251e4c90..e2879cc84ee0 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -444,12 +444,12 @@ static const struct dpu_lm_sub_blks qcm2290_lm_sblk = { * DSPP sub blocks config */ static const struct dpu_dspp_sub_blks msm8998_dspp_sblk = { - .pcc = {.id = DPU_DSPP_PCC, .base = 0x1700, + .pcc = {.name = "pcc", .id = DPU_DSPP_PCC, .base = 0x1700, .len = 0x90, .version = 0x10007}, }; static const struct dpu_dspp_sub_blks sm8150_dspp_sblk = { - .pcc = {.id = DPU_DSPP_PCC, .base = 0x1700, + .pcc = {.name = "pcc", .id = DPU_DSPP_PCC, .base = 0x1700, .len = 0x90, .version = 0x4}, }; @@ -465,19 +465,19 @@ static const struct dpu_dspp_sub_blks sm8150_dspp_sblk = { * PINGPONG sub blocks config */ static const struct dpu_pingpong_sub_blks sdm845_pp_sblk_te = { - .te2 = {.id = DPU_PINGPONG_TE2, .base = 0x2000, .len = 0x0, + .te2 = {.name = "te2", .id = DPU_PINGPONG_TE2, .base = 0x2000, .len = 0x0, .version = 0x1}, - .dither = {.id = DPU_PINGPONG_DITHER, .base = 0x30e0, + .dither = {.name = "dither", .id = DPU_PINGPONG_DITHER, .base = 0x30e0, .len = 0x20, .version = 0x1}, }; static const struct dpu_pingpong_sub_blks sdm845_pp_sblk = { - .dither = {.id = DPU_PINGPONG_DITHER, .base = 0x30e0, + .dither = {.name = "dither", .id = DPU_PINGPONG_DITHER, .base = 0x30e0, .len = 0x20, .version = 0x1}, }; static const struct dpu_pingpong_sub_blks sc7280_pp_sblk = { - .dither = {.id = DPU_PINGPONG_DITHER, .base = 0xe0, + .dither = {.name = "dither", .id = DPU_PINGPONG_DITHER, .base = 0xe0, .len = 0x20, .version = 0x2}, }; @@ -517,13 +517,13 @@ static const struct dpu_pingpong_sub_blks sc7280_pp_sblk = { * DSC sub blocks config */ static const struct dpu_dsc_sub_blks dsc_sblk_0 = { - .enc = {.base = 0x100, .len = 0x9c}, - .ctl = {.base = 0xF00, .len = 0x10}, + .enc = {.name = "enc", .base = 0x100, .len = 0x9c}, + .ctl = {.name = "ctl", .base = 0xF00, .len = 0x10}, }; static const struct dpu_dsc_sub_blks dsc_sblk_1 = { - .enc = {.base = 0x200, .len = 0x9c}, - .ctl = {.base = 0xF80, .len = 0x10}, + .enc = {.name = "enc", .base = 0x200, .len = 0x9c}, + .ctl = {.name = "ctl", .base = 0xF80, .len = 0x10}, }; #define DSC_BLK(_name, _id, _base, _features) \ -- 2.25.1
[PATCH v5 2/6] drm/msm/dpu: Drop unused num argument from relevant macros
Drop unused parameter "num" from VIG_SBLK_NOSCALE and DMA sub-block macros. Update calls to relevant macros to reflect change. Reviewed-by: Abhinav Kumar Reviewed-by: Dmitry Baryshkov Signed-off-by: Ryan McCann --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 20 ++-- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c index dd2f89ada043..1291251e4c90 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -288,7 +288,7 @@ static const uint32_t wb2_formats[] = { .rotation_cfg = rot_cfg, \ } -#define _DMA_SBLK(num, sdma_pri) \ +#define _DMA_SBLK(sdma_pri) \ { \ .maxdwnscale = SSPP_UNITY_SCALE, \ .maxupscale = SSPP_UNITY_SCALE, \ @@ -323,10 +323,10 @@ static const struct dpu_sspp_sub_blks sdm845_vig_sblk_2 = static const struct dpu_sspp_sub_blks sdm845_vig_sblk_3 = _VIG_SBLK("3", 8, DPU_SSPP_SCALER_QSEED3); -static const struct dpu_sspp_sub_blks sdm845_dma_sblk_0 = _DMA_SBLK("8", 1); -static const struct dpu_sspp_sub_blks sdm845_dma_sblk_1 = _DMA_SBLK("9", 2); -static const struct dpu_sspp_sub_blks sdm845_dma_sblk_2 = _DMA_SBLK("10", 3); -static const struct dpu_sspp_sub_blks sdm845_dma_sblk_3 = _DMA_SBLK("11", 4); +static const struct dpu_sspp_sub_blks sdm845_dma_sblk_0 = _DMA_SBLK(1); +static const struct dpu_sspp_sub_blks sdm845_dma_sblk_1 = _DMA_SBLK(2); +static const struct dpu_sspp_sub_blks sdm845_dma_sblk_2 = _DMA_SBLK(3); +static const struct dpu_sspp_sub_blks sdm845_dma_sblk_3 = _DMA_SBLK(4); #define SSPP_BLK(_name, _id, _base, _len, _features, \ _sblk, _xinid, _type, _clkctrl) \ @@ -366,10 +366,10 @@ static const struct dpu_sspp_sub_blks sm8550_vig_sblk_2 = _VIG_SBLK("2", 9, DPU_SSPP_SCALER_QSEED4); static const struct dpu_sspp_sub_blks sm8550_vig_sblk_3 = _VIG_SBLK("3", 10, DPU_SSPP_SCALER_QSEED4); -static const struct dpu_sspp_sub_blks sm8550_dma_sblk_4 = _DMA_SBLK("12", 5); -static const struct dpu_sspp_sub_blks sm8550_dma_sblk_5 = _DMA_SBLK("13", 6); +static const struct dpu_sspp_sub_blks sm8550_dma_sblk_4 = _DMA_SBLK(5); +static const struct dpu_sspp_sub_blks sm8550_dma_sblk_5 = _DMA_SBLK(6); -#define _VIG_SBLK_NOSCALE(num, sdma_pri) \ +#define _VIG_SBLK_NOSCALE(sdma_pri) \ { \ .maxdwnscale = SSPP_UNITY_SCALE, \ .maxupscale = SSPP_UNITY_SCALE, \ @@ -380,8 +380,8 @@ static const struct dpu_sspp_sub_blks sm8550_dma_sblk_5 = _DMA_SBLK("13", 6); .virt_num_formats = ARRAY_SIZE(plane_formats), \ } -static const struct dpu_sspp_sub_blks qcm2290_vig_sblk_0 = _VIG_SBLK_NOSCALE("0", 2); -static const struct dpu_sspp_sub_blks qcm2290_dma_sblk_0 = _DMA_SBLK("8", 1); +static const struct dpu_sspp_sub_blks qcm2290_vig_sblk_0 = _VIG_SBLK_NOSCALE(2); +static const struct dpu_sspp_sub_blks qcm2290_dma_sblk_0 = _DMA_SBLK(1); /* * MIXER sub blocks config -- 2.25.1
[PATCH v5 0/6] Add support to print sub-block registers in dpu hw catalog
The purpose of this patch series is to add support to print the registers of sub-blocks in the DPU hardware catalog and fix the order in which all hardware blocks are dumped for a device core dump. This involves: 1. Changing data structure from stack to queue to fix the printing order of the device core dump. 2. Removing redundant suffix of sub-block names. 3. Removing redundant prefix of sub-block names. 4. Eliminating unused variable from relevant macros. 5. Defining names for sub-blocks that have not yet been defined. 6. Implementing wrapper function that prints the registers of sub-blocks when there is a need. Sample Output of the sspp_0 block and its sub-blocks for devcore dump: ==sspp_0== ...registers ... sspp_0_scaler ... ... sspp_0_csc ... ... next_block ... This series depends on https://patchwork.freedesktop.org/series/119776/. --- Changes in v5: - Fixed indentation in refactor main block printing patch - Fixed formatting issues to satisfy checkpatch - Instead of passing 0 for DSC block, used actual length thanks to https://patchwork.freedesktop.org/series/119776/ - Link to v4: https://lore.kernel.org/r/20230622-devcoredump_patch-v4-0-e304ddbe9...@quicinc.com Changes in v4: - Added review tags - Link to v3: https://lore.kernel.org/r/20230622-devcoredump_patch-v3-0-83601b72e...@quicinc.com Changes in v3: - Split sub-block changes and main block changes into two commits - Corrected typo in comment located in DSC for loop block - Eliminated variables mmio and base - Dropped unnecessary "%s" - Link to v2: https://lore.kernel.org/r/20230622-devcoredump_patch-v2-0-9e90a87d3...@quicinc.com Changes in v2: - Changed spelling "sub block" to "sub-block" or "sblk". - Capitalized DPU. - Eliminated multiplexer/wrapper function. Inlined instead. - Changed if statements from feature checks to length checks. - Squashed prefix and suffix patch into one. - Link to v1: https://lore.kernel.org/r/20230622-devcoredump_patch-v1-0-3b2cdcc6a...@quicinc.com --- Ryan McCann (6): drm/msm: Update dev core dump to not print backwards drm/msm/dpu: Drop unused num argument from relevant macros drm/msm/dpu: Define names for unnamed sblks drm/msm/dpu: Remove redundant prefix/suffix in name of sub-blocks drm/msm/dpu: Refactor printing of main blocks in device core dump drm/msm/dpu: Update dev core dump to dump registers of sub-blocks drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c| 90 +++ drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 74 +++ drivers/gpu/drm/msm/disp/msm_disp_snapshot_util.c | 2 +- 3 files changed, 104 insertions(+), 62 deletions(-) --- base-commit: a92b5625851098af521cd92e4c518429b661c8f4 change-id: 20230622-devcoredump_patch-df7e8f6fd632 Best regards, -- Ryan McCann
[PATCH v5 5/6] drm/msm/dpu: Refactor printing of main blocks in device core dump
Currently, the names of main blocks are hardcoded into the msm_disp_snapshot_add_block function rather than using the name that already exists in the catalog. Change this to take the name directly from the catalog instead of hardcoding it. Signed-off-by: Ryan McCann --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 16 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index aa8499de1b9f..7a2787279ba0 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -900,37 +900,37 @@ static void dpu_kms_mdp_snapshot(struct msm_disp_state *disp_state, struct msm_k /* dump CTL sub-blocks HW regs info */ for (i = 0; i < cat->ctl_count; i++) msm_disp_snapshot_add_block(disp_state, cat->ctl[i].len, - dpu_kms->mmio + cat->ctl[i].base, "ctl_%d", i); + dpu_kms->mmio + cat->ctl[i].base, cat->ctl[i].name); /* dump DSPP sub-blocks HW regs info */ for (i = 0; i < cat->dspp_count; i++) msm_disp_snapshot_add_block(disp_state, cat->dspp[i].len, - dpu_kms->mmio + cat->dspp[i].base, "dspp_%d", i); + dpu_kms->mmio + cat->dspp[i].base, cat->dspp[i].name); /* dump INTF sub-blocks HW regs info */ for (i = 0; i < cat->intf_count; i++) msm_disp_snapshot_add_block(disp_state, cat->intf[i].len, - dpu_kms->mmio + cat->intf[i].base, "intf_%d", i); + dpu_kms->mmio + cat->intf[i].base, cat->intf[i].name); /* dump PP sub-blocks HW regs info */ for (i = 0; i < cat->pingpong_count; i++) msm_disp_snapshot_add_block(disp_state, cat->pingpong[i].len, - dpu_kms->mmio + cat->pingpong[i].base, "pingpong_%d", i); + dpu_kms->mmio + cat->pingpong[i].base, cat->pingpong[i].name); /* dump SSPP sub-blocks HW regs info */ for (i = 0; i < cat->sspp_count; i++) msm_disp_snapshot_add_block(disp_state, cat->sspp[i].len, - dpu_kms->mmio + cat->sspp[i].base, "sspp_%d", i); + dpu_kms->mmio + cat->sspp[i].base, cat->sspp[i].name); /* dump LM sub-blocks HW regs info */ for (i = 0; i < cat->mixer_count; i++) msm_disp_snapshot_add_block(disp_state, cat->mixer[i].len, - dpu_kms->mmio + cat->mixer[i].base, "lm_%d", i); + dpu_kms->mmio + cat->mixer[i].base, cat->mixer[i].name); /* dump WB sub-blocks HW regs info */ for (i = 0; i < cat->wb_count; i++) msm_disp_snapshot_add_block(disp_state, cat->wb[i].len, - dpu_kms->mmio + cat->wb[i].base, "wb_%d", i); + dpu_kms->mmio + cat->wb[i].base, cat->wb[i].name); if (cat->mdp[0].features & BIT(DPU_MDP_PERIPH_0_REMOVED)) { msm_disp_snapshot_add_block(disp_state, MDP_PERIPH_TOP0, @@ -945,7 +945,7 @@ static void dpu_kms_mdp_snapshot(struct msm_disp_state *disp_state, struct msm_k /* dump DSC sub-blocks HW regs info */ for (i = 0; i < cat->dsc_count; i++) msm_disp_snapshot_add_block(disp_state, cat->dsc[i].len, - dpu_kms->mmio + cat->dsc[i].base, "dsc_%d", i); + dpu_kms->mmio + cat->dsc[i].base, cat->dsc[i].name); pm_runtime_put_sync(_kms->pdev->dev); } -- 2.25.1
[PATCH v5 6/6] drm/msm/dpu: Update dev core dump to dump registers of sub-blocks
Currently, the device core dump mechanism does not dump registers of sub-blocks within the DSPP, SSPP, DSC, and PINGPONG blocks. Edit dpu_kms_mdp_snapshot function to account for sub-blocks. Signed-off-by: Ryan McCann --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 66 +++-- 1 file changed, 54 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index 7a2787279ba0..f7199a5c45ab 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -890,6 +890,7 @@ static void dpu_kms_mdp_snapshot(struct msm_disp_state *disp_state, struct msm_k int i; struct dpu_kms *dpu_kms; const struct dpu_mdss_cfg *cat; + void __iomem *base; dpu_kms = to_dpu_kms(kms); @@ -903,9 +904,16 @@ static void dpu_kms_mdp_snapshot(struct msm_disp_state *disp_state, struct msm_k dpu_kms->mmio + cat->ctl[i].base, cat->ctl[i].name); /* dump DSPP sub-blocks HW regs info */ - for (i = 0; i < cat->dspp_count; i++) - msm_disp_snapshot_add_block(disp_state, cat->dspp[i].len, - dpu_kms->mmio + cat->dspp[i].base, cat->dspp[i].name); + for (i = 0; i < cat->dspp_count; i++) { + base = dpu_kms->mmio + cat->dspp[i].base; + msm_disp_snapshot_add_block(disp_state, cat->dspp[i].len, base, cat->dspp[i].name); + + if (cat->dspp[i].sblk && cat->dspp[i].sblk->pcc.len > 0) + msm_disp_snapshot_add_block(disp_state, cat->dspp[i].sblk->pcc.len, + base + cat->dspp[i].sblk->pcc.base, "%s_%s", + cat->dspp[i].name, + cat->dspp[i].sblk->pcc.name); + } /* dump INTF sub-blocks HW regs info */ for (i = 0; i < cat->intf_count; i++) @@ -913,14 +921,37 @@ static void dpu_kms_mdp_snapshot(struct msm_disp_state *disp_state, struct msm_k dpu_kms->mmio + cat->intf[i].base, cat->intf[i].name); /* dump PP sub-blocks HW regs info */ - for (i = 0; i < cat->pingpong_count; i++) - msm_disp_snapshot_add_block(disp_state, cat->pingpong[i].len, - dpu_kms->mmio + cat->pingpong[i].base, cat->pingpong[i].name); + for (i = 0; i < cat->pingpong_count; i++) { + base = dpu_kms->mmio + cat->pingpong[i].base; + msm_disp_snapshot_add_block(disp_state, cat->pingpong[i].len, base, + cat->pingpong[i].name); + + /* TE2 sub-block has length of 0, so will not print it */ + + if (cat->pingpong[i].sblk && cat->pingpong[i].sblk->dither.len > 0) + msm_disp_snapshot_add_block(disp_state, cat->pingpong[i].sblk->dither.len, + base + cat->pingpong[i].sblk->dither.base, + "%s_%s", cat->pingpong[i].name, + cat->pingpong[i].sblk->dither.name); + } /* dump SSPP sub-blocks HW regs info */ - for (i = 0; i < cat->sspp_count; i++) - msm_disp_snapshot_add_block(disp_state, cat->sspp[i].len, - dpu_kms->mmio + cat->sspp[i].base, cat->sspp[i].name); + for (i = 0; i < cat->sspp_count; i++) { + base = dpu_kms->mmio + cat->sspp[i].base; + msm_disp_snapshot_add_block(disp_state, cat->sspp[i].len, base, cat->sspp[i].name); + + if (cat->sspp[i].sblk && cat->sspp[i].sblk->scaler_blk.len > 0) + msm_disp_snapshot_add_block(disp_state, cat->sspp[i].sblk->scaler_blk.len, + base + cat->sspp[i].sblk->scaler_blk.base, + "%s_%s", cat->sspp[i].name, + cat->sspp[i].sblk->scaler_blk.name); + + if (cat->sspp[i].sblk && cat->sspp[i].sblk->csc_blk.len > 0) + msm_disp_snapshot_add_block(disp_state, cat->sspp[i].sblk->csc_blk.len, + base + cat->sspp[i].sblk->csc_blk.base, + "%s_%s", cat->sspp[i].name, + cat->sspp[i].sblk->csc_blk.name); + } /* dump LM sub-blocks HW regs info */ for (i = 0; i < cat->mixer_count; i++) @@ -943,9 +974,20 @@ static void dpu_kms_mdp_snapshot(struct msm_disp_state *disp_state, struct msm_k } /* dump DSC sub-blocks HW regs info */ - for (i = 0; i < cat->dsc_count; i++) -
[Patch v2] drm/ttm: Use init_on_free to delay release TTM BOs
Delay release TTM BOs when the kernel default setting is init_on_free. This offloads the overhead of clearing the system memory to the work item and potentially a different CPU. This could be very beneficial when the application does a lot of malloc/free style allocations of system memory. Reviewed-by: Christian König . Signed-off-by: Rajneesh Bhardwaj --- Changes in v2: - Updated commit message as per Christian's feedback drivers/gpu/drm/ttm/ttm_bo.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 326a3d13a829..bd2e7e4f497a 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -347,6 +347,7 @@ static void ttm_bo_release(struct kref *kref) if (!dma_resv_test_signaled(bo->base.resv, DMA_RESV_USAGE_BOOKKEEP) || + (want_init_on_free() && (bo->ttm != NULL)) || !dma_resv_trylock(bo->base.resv)) { /* The BO is not idle, resurrect it for delayed destroy */ ttm_bo_flush_all_fences(bo); -- 2.17.1
[PATCH 17/17] drm/msm: drop mdp_get_formats()
Drop the function mdp_get_formats(), which became unused after converting both MDP4 and MDP5 planes to use static formats arrays. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/mdp_format.c | 24 drivers/gpu/drm/msm/disp/mdp_kms.h| 1 - 2 files changed, 25 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/mdp_format.c b/drivers/gpu/drm/msm/disp/mdp_format.c index ba9abe8b3acc..0fe430af9523 100644 --- a/drivers/gpu/drm/msm/disp/mdp_format.c +++ b/drivers/gpu/drm/msm/disp/mdp_format.c @@ -183,30 +183,6 @@ const uint32_t mdp_rgb_yuv_formats[] = { size_t mdp_rgb_yuv_num_formats = ARRAY_SIZE(mdp_rgb_yuv_formats); -/* - * Note: - * @rgb_only must be set to true, when requesting - * supported formats for RGB pipes. - */ -uint32_t mdp_get_formats(uint32_t *pixel_formats, uint32_t max_formats, - bool rgb_only) -{ - uint32_t i; - for (i = 0; i < ARRAY_SIZE(formats); i++) { - const struct mdp_format *f = [i]; - - if (i == max_formats) - break; - - if (rgb_only && MDP_FORMAT_IS_YUV(f)) - break; - - pixel_formats[i] = f->base.pixel_format; - } - - return i; -} - const struct msm_format *mdp_get_format(struct msm_kms *kms, uint32_t format, uint64_t modifier) { diff --git a/drivers/gpu/drm/msm/disp/mdp_kms.h b/drivers/gpu/drm/msm/disp/mdp_kms.h index 11402a859574..1b2ccf7e7de6 100644 --- a/drivers/gpu/drm/msm/disp/mdp_kms.h +++ b/drivers/gpu/drm/msm/disp/mdp_kms.h @@ -91,7 +91,6 @@ struct mdp_format { #define to_mdp_format(x) container_of(x, struct mdp_format, base) #define MDP_FORMAT_IS_YUV(mdp_format) ((mdp_format)->is_yuv) -uint32_t mdp_get_formats(uint32_t *formats, uint32_t max_formats, bool rgb_only); const struct msm_format *mdp_get_format(struct msm_kms *kms, uint32_t format, uint64_t modifier); extern const uint32_t mdp_rgb_formats[]; -- 2.39.2
[PATCH 15/17] drm/msm/mdp4: use drmm-managed allocation for mdp4_lcdc_encoder
Change struct mdp4_lcdc_encoder allocation to use drmm_encoder_alloc(). This removes the need to perform any actions on this encoder destruction. Signed-off-by: Dmitry Baryshkov --- .../gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c | 36 --- 1 file changed, 7 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c index 67c118bb30ca..576995ddce37 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c @@ -30,18 +30,6 @@ static struct mdp4_kms *get_kms(struct drm_encoder *encoder) return to_mdp4_kms(to_mdp_kms(priv->kms)); } -static void mdp4_lcdc_encoder_destroy(struct drm_encoder *encoder) -{ - struct mdp4_lcdc_encoder *mdp4_lcdc_encoder = - to_mdp4_lcdc_encoder(encoder); - drm_encoder_cleanup(encoder); - kfree(mdp4_lcdc_encoder); -} - -static const struct drm_encoder_funcs mdp4_lcdc_encoder_funcs = { - .destroy = mdp4_lcdc_encoder_destroy, -}; - /* this should probably be a helper: */ static struct drm_connector *get_connector(struct drm_encoder *encoder) { @@ -377,30 +365,26 @@ long mdp4_lcdc_round_pixclk(struct drm_encoder *encoder, unsigned long rate) struct drm_encoder *mdp4_lcdc_encoder_init(struct drm_device *dev, struct device_node *panel_node) { - struct drm_encoder *encoder = NULL; + struct drm_encoder *encoder; struct mdp4_lcdc_encoder *mdp4_lcdc_encoder; int ret; - mdp4_lcdc_encoder = kzalloc(sizeof(*mdp4_lcdc_encoder), GFP_KERNEL); - if (!mdp4_lcdc_encoder) { - ret = -ENOMEM; - goto fail; - } + mdp4_lcdc_encoder = drmm_encoder_alloc(dev, struct mdp4_lcdc_encoder, base, + NULL, DRM_MODE_ENCODER_LVDS, NULL); + if (IS_ERR(mdp4_lcdc_encoder)) + return ERR_CAST(mdp4_lcdc_encoder); mdp4_lcdc_encoder->panel_node = panel_node; encoder = _lcdc_encoder->base; - drm_encoder_init(dev, encoder, _lcdc_encoder_funcs, -DRM_MODE_ENCODER_LVDS, NULL); drm_encoder_helper_add(encoder, _lcdc_encoder_helper_funcs); /* TODO: do we need different pll in other cases? */ mdp4_lcdc_encoder->lcdc_clk = mpd4_lvds_pll_init(dev); if (IS_ERR(mdp4_lcdc_encoder->lcdc_clk)) { DRM_DEV_ERROR(dev->dev, "failed to get lvds_clk\n"); - ret = PTR_ERR(mdp4_lcdc_encoder->lcdc_clk); - goto fail; + return ERR_CAST(mdp4_lcdc_encoder->lcdc_clk); } /* TODO: different regulators in other cases? */ @@ -412,13 +396,7 @@ struct drm_encoder *mdp4_lcdc_encoder_init(struct drm_device *dev, ARRAY_SIZE(mdp4_lcdc_encoder->regs), mdp4_lcdc_encoder->regs); if (ret) - goto fail; + return ERR_PTR(ret); return encoder; - -fail: - if (encoder) - mdp4_lcdc_encoder_destroy(encoder); - - return ERR_PTR(ret); } -- 2.39.2
[PATCH 11/17] drm/msm/mdp4: use bulk regulators API for LCDC encoder
Switch mdp4_lcdc_encoder to using regulator_bulk_* API instead of enumerating regulators by hand. Signed-off-by: Dmitry Baryshkov --- .../gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c | 51 ++- 1 file changed, 15 insertions(+), 36 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c index 10eb3e5b218e..67c118bb30ca 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c @@ -18,7 +18,7 @@ struct mdp4_lcdc_encoder { struct drm_panel *panel; struct clk *lcdc_clk; unsigned long int pixclock; - struct regulator *regs[3]; + struct regulator_bulk_data regs[3]; bool enabled; uint32_t bsc; }; @@ -271,12 +271,10 @@ static void mdp4_lcdc_encoder_mode_set(struct drm_encoder *encoder, static void mdp4_lcdc_encoder_disable(struct drm_encoder *encoder) { - struct drm_device *dev = encoder->dev; struct mdp4_lcdc_encoder *mdp4_lcdc_encoder = to_mdp4_lcdc_encoder(encoder); struct mdp4_kms *mdp4_kms = get_kms(encoder); struct drm_panel *panel; - int i, ret; if (WARN_ON(!mdp4_lcdc_encoder->enabled)) return; @@ -301,11 +299,8 @@ static void mdp4_lcdc_encoder_disable(struct drm_encoder *encoder) clk_disable_unprepare(mdp4_lcdc_encoder->lcdc_clk); - for (i = 0; i < ARRAY_SIZE(mdp4_lcdc_encoder->regs); i++) { - ret = regulator_disable(mdp4_lcdc_encoder->regs[i]); - if (ret) - DRM_DEV_ERROR(dev->dev, "failed to disable regulator: %d\n", ret); - } + regulator_bulk_disable(ARRAY_SIZE(mdp4_lcdc_encoder->regs), + mdp4_lcdc_encoder->regs); mdp4_lcdc_encoder->enabled = false; } @@ -319,7 +314,7 @@ static void mdp4_lcdc_encoder_enable(struct drm_encoder *encoder) struct mdp4_kms *mdp4_kms = get_kms(encoder); struct drm_panel *panel; uint32_t config; - int i, ret; + int ret; if (WARN_ON(mdp4_lcdc_encoder->enabled)) return; @@ -339,11 +334,10 @@ static void mdp4_lcdc_encoder_enable(struct drm_encoder *encoder) mdp4_crtc_set_config(encoder->crtc, config); mdp4_crtc_set_intf(encoder->crtc, INTF_LCDC_DTV, 0); - for (i = 0; i < ARRAY_SIZE(mdp4_lcdc_encoder->regs); i++) { - ret = regulator_enable(mdp4_lcdc_encoder->regs[i]); - if (ret) - DRM_DEV_ERROR(dev->dev, "failed to enable regulator: %d\n", ret); - } + ret = regulator_bulk_enable(ARRAY_SIZE(mdp4_lcdc_encoder->regs), + mdp4_lcdc_encoder->regs); + if (ret) + DRM_DEV_ERROR(dev->dev, "failed to enable regulators: %d\n", ret); DBG("setting lcdc_clk=%lu", pc); ret = clk_set_rate(mdp4_lcdc_encoder->lcdc_clk, pc); @@ -385,7 +379,6 @@ struct drm_encoder *mdp4_lcdc_encoder_init(struct drm_device *dev, { struct drm_encoder *encoder = NULL; struct mdp4_lcdc_encoder *mdp4_lcdc_encoder; - struct regulator *reg; int ret; mdp4_lcdc_encoder = kzalloc(sizeof(*mdp4_lcdc_encoder), GFP_KERNEL); @@ -411,29 +404,15 @@ struct drm_encoder *mdp4_lcdc_encoder_init(struct drm_device *dev, } /* TODO: different regulators in other cases? */ - reg = devm_regulator_get(dev->dev, "lvds-vccs-3p3v"); - if (IS_ERR(reg)) { - ret = PTR_ERR(reg); - DRM_DEV_ERROR(dev->dev, "failed to get lvds-vccs-3p3v: %d\n", ret); - goto fail; - } - mdp4_lcdc_encoder->regs[0] = reg; - - reg = devm_regulator_get(dev->dev, "lvds-pll-vdda"); - if (IS_ERR(reg)) { - ret = PTR_ERR(reg); - DRM_DEV_ERROR(dev->dev, "failed to get lvds-pll-vdda: %d\n", ret); - goto fail; - } - mdp4_lcdc_encoder->regs[1] = reg; + mdp4_lcdc_encoder->regs[0].supply = "lvds-vccs-3p3v"; + mdp4_lcdc_encoder->regs[1].supply = "lvds-vccs-3p3v"; + mdp4_lcdc_encoder->regs[2].supply = "lvds-vdda"; - reg = devm_regulator_get(dev->dev, "lvds-vdda"); - if (IS_ERR(reg)) { - ret = PTR_ERR(reg); - DRM_DEV_ERROR(dev->dev, "failed to get lvds-vdda: %d\n", ret); + ret = devm_regulator_bulk_get(dev->dev, + ARRAY_SIZE(mdp4_lcdc_encoder->regs), + mdp4_lcdc_encoder->regs); + if (ret) goto fail; - } - mdp4_lcdc_encoder->regs[2] = reg; return encoder; -- 2.39.2
[PATCH 14/17] drm/msm/mdp4: use drmm-managed allocation for mdp4_dtv_encoder
Change struct mdp4_dtv_encoder allocation to use drmm_encoder_alloc(). This removes the need to perform any actions on this encoder destruction. Signed-off-by: Dmitry Baryshkov --- .../gpu/drm/msm/disp/mdp4/mdp4_dtv_encoder.c | 37 --- 1 file changed, 7 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_dtv_encoder.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_dtv_encoder.c index 88645dbc3785..3b70764b48c4 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_dtv_encoder.c +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_dtv_encoder.c @@ -25,17 +25,6 @@ static struct mdp4_kms *get_kms(struct drm_encoder *encoder) return to_mdp4_kms(to_mdp_kms(priv->kms)); } -static void mdp4_dtv_encoder_destroy(struct drm_encoder *encoder) -{ - struct mdp4_dtv_encoder *mdp4_dtv_encoder = to_mdp4_dtv_encoder(encoder); - drm_encoder_cleanup(encoder); - kfree(mdp4_dtv_encoder); -} - -static const struct drm_encoder_funcs mdp4_dtv_encoder_funcs = { - .destroy = mdp4_dtv_encoder_destroy, -}; - static void mdp4_dtv_encoder_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) @@ -173,41 +162,29 @@ long mdp4_dtv_round_pixclk(struct drm_encoder *encoder, unsigned long rate) /* initialize encoder */ struct drm_encoder *mdp4_dtv_encoder_init(struct drm_device *dev) { - struct drm_encoder *encoder = NULL; + struct drm_encoder *encoder; struct mdp4_dtv_encoder *mdp4_dtv_encoder; - int ret; - mdp4_dtv_encoder = kzalloc(sizeof(*mdp4_dtv_encoder), GFP_KERNEL); - if (!mdp4_dtv_encoder) { - ret = -ENOMEM; - goto fail; - } + mdp4_dtv_encoder = drmm_encoder_alloc(dev, struct mdp4_dtv_encoder, base, + NULL, DRM_MODE_ENCODER_TMDS, NULL); + if (IS_ERR(mdp4_dtv_encoder)) + return ERR_CAST(mdp4_dtv_encoder); encoder = _dtv_encoder->base; - drm_encoder_init(dev, encoder, _dtv_encoder_funcs, -DRM_MODE_ENCODER_TMDS, NULL); drm_encoder_helper_add(encoder, _dtv_encoder_helper_funcs); mdp4_dtv_encoder->hdmi_clk = devm_clk_get(dev->dev, "hdmi_clk"); if (IS_ERR(mdp4_dtv_encoder->hdmi_clk)) { DRM_DEV_ERROR(dev->dev, "failed to get hdmi_clk\n"); - ret = PTR_ERR(mdp4_dtv_encoder->hdmi_clk); - goto fail; + return ERR_CAST(mdp4_dtv_encoder->hdmi_clk); } mdp4_dtv_encoder->mdp_clk = devm_clk_get(dev->dev, "tv_clk"); if (IS_ERR(mdp4_dtv_encoder->mdp_clk)) { DRM_DEV_ERROR(dev->dev, "failed to get tv_clk\n"); - ret = PTR_ERR(mdp4_dtv_encoder->mdp_clk); - goto fail; + return ERR_CAST(mdp4_dtv_encoder->mdp_clk); } return encoder; - -fail: - if (encoder) - mdp4_dtv_encoder_destroy(encoder); - - return ERR_PTR(ret); } -- 2.39.2
[PATCH 16/17] drm/msm/mdp4: use drmm-managed allocation for mdp4_plane
Change struct mdp4_plane allocation to use drmm_plane_alloc(). This removes the need to perform any actions on plane destruction. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c | 59 -- 1 file changed, 20 insertions(+), 39 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c index b689b618da78..1149e6721534 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c @@ -20,12 +20,6 @@ struct mdp4_plane { const char *name; enum mdp4_pipe pipe; - - uint32_t caps; - uint32_t nformats; - uint32_t formats[32]; - - bool enabled; }; #define to_mdp4_plane(x) container_of(x, struct mdp4_plane, base) @@ -59,15 +53,6 @@ static struct mdp4_kms *get_kms(struct drm_plane *plane) return to_mdp4_kms(to_mdp_kms(priv->kms)); } -static void mdp4_plane_destroy(struct drm_plane *plane) -{ - struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane); - - drm_plane_cleanup(plane); - - kfree(mdp4_plane); -} - /* helper to install properties which are common to planes and crtcs */ static void mdp4_plane_install_properties(struct drm_plane *plane, struct drm_mode_object *obj) @@ -85,7 +70,6 @@ static int mdp4_plane_set_property(struct drm_plane *plane, static const struct drm_plane_funcs mdp4_plane_funcs = { .update_plane = drm_atomic_helper_update_plane, .disable_plane = drm_atomic_helper_disable_plane, - .destroy = mdp4_plane_destroy, .set_property = mdp4_plane_set_property, .reset = drm_atomic_helper_plane_reset, .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, @@ -377,31 +361,34 @@ struct drm_plane *mdp4_plane_init(struct drm_device *dev, { struct drm_plane *plane = NULL; struct mdp4_plane *mdp4_plane; - int ret; enum drm_plane_type type; + uint32_t pipe_caps; + const uint32_t *formats; + size_t nformats; - mdp4_plane = kzalloc(sizeof(*mdp4_plane), GFP_KERNEL); - if (!mdp4_plane) { - ret = -ENOMEM; - goto fail; + type = private_plane ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY; + + pipe_caps = mdp4_pipe_caps(pipe_id); + if (pipe_supports_yuv(pipe_caps)) { + formats = mdp_rgb_yuv_formats; + nformats = mdp_rgb_yuv_num_formats; + } else { + formats = mdp_rgb_formats; + nformats = mdp_rgb_num_formats; } + mdp4_plane = drmm_universal_plane_alloc(dev, struct mdp4_plane, base, + 0xff, _plane_funcs, + formats, nformats, + supported_format_modifiers, + type, NULL); + if (IS_ERR(mdp4_plane)) + return ERR_CAST(mdp4_plane); + plane = _plane->base; mdp4_plane->pipe = pipe_id; mdp4_plane->name = pipe_names[pipe_id]; - mdp4_plane->caps = mdp4_pipe_caps(pipe_id); - - mdp4_plane->nformats = mdp_get_formats(mdp4_plane->formats, - ARRAY_SIZE(mdp4_plane->formats), - !pipe_supports_yuv(mdp4_plane->caps)); - - type = private_plane ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY; - ret = drm_universal_plane_init(dev, plane, 0xff, _plane_funcs, -mdp4_plane->formats, mdp4_plane->nformats, -supported_format_modifiers, type, NULL); - if (ret) - goto fail; drm_plane_helper_add(plane, _plane_helper_funcs); @@ -410,10 +397,4 @@ struct drm_plane *mdp4_plane_init(struct drm_device *dev, drm_plane_enable_fb_damage_clips(plane); return plane; - -fail: - if (plane) - mdp4_plane_destroy(plane); - - return ERR_PTR(ret); } -- 2.39.2
[PATCH 09/17] drm/msm/mdp5: use drmm-managed allocation for mdp5_encoder
Change struct mdp5_encoder allocation to use drmm_encoder_alloc(). This removes the need to perform any actions on encoder destruction. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/mdp5/mdp5_encoder.c | 29 +++- 1 file changed, 4 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_encoder.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_encoder.c index 79d67c495780..8db97083e14d 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_encoder.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_encoder.c @@ -16,17 +16,6 @@ static struct mdp5_kms *get_kms(struct drm_encoder *encoder) return to_mdp5_kms(to_mdp_kms(priv->kms)); } -static void mdp5_encoder_destroy(struct drm_encoder *encoder) -{ - struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder); - drm_encoder_cleanup(encoder); - kfree(mdp5_encoder); -} - -static const struct drm_encoder_funcs mdp5_encoder_funcs = { - .destroy = mdp5_encoder_destroy, -}; - static void mdp5_vid_encoder_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) @@ -342,13 +331,11 @@ struct drm_encoder *mdp5_encoder_init(struct drm_device *dev, struct mdp5_encoder *mdp5_encoder; int enc_type = (intf->type == INTF_DSI) ? DRM_MODE_ENCODER_DSI : DRM_MODE_ENCODER_TMDS; - int ret; - mdp5_encoder = kzalloc(sizeof(*mdp5_encoder), GFP_KERNEL); - if (!mdp5_encoder) { - ret = -ENOMEM; - goto fail; - } + mdp5_encoder = drmm_encoder_alloc(dev, struct mdp5_encoder, base, + NULL, enc_type, NULL); + if (IS_ERR(mdp5_encoder)) + return ERR_CAST(mdp5_encoder); encoder = _encoder->base; mdp5_encoder->ctl = ctl; @@ -356,15 +343,7 @@ struct drm_encoder *mdp5_encoder_init(struct drm_device *dev, spin_lock_init(_encoder->intf_lock); - drm_encoder_init(dev, encoder, _encoder_funcs, enc_type, NULL); - drm_encoder_helper_add(encoder, _encoder_helper_funcs); return encoder; - -fail: - if (encoder) - mdp5_encoder_destroy(encoder); - - return ERR_PTR(ret); } -- 2.39.2
[PATCH 13/17] drm/msm/mdp4: use drmm-managed allocation for mdp4_dsi_encoder
Change struct mdp4_dsi_encoder allocation to use drmm_encoder_alloc(). This removes the need to perform any actions on this encoder destruction. Signed-off-by: Dmitry Baryshkov --- .../gpu/drm/msm/disp/mdp4/mdp4_dsi_encoder.c | 32 +++ 1 file changed, 5 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_dsi_encoder.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_dsi_encoder.c index 39b8fe53c29d..74dafe7106be 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_dsi_encoder.c +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_dsi_encoder.c @@ -26,18 +26,6 @@ static struct mdp4_kms *get_kms(struct drm_encoder *encoder) return to_mdp4_kms(to_mdp_kms(priv->kms)); } -static void mdp4_dsi_encoder_destroy(struct drm_encoder *encoder) -{ - struct mdp4_dsi_encoder *mdp4_dsi_encoder = to_mdp4_dsi_encoder(encoder); - - drm_encoder_cleanup(encoder); - kfree(mdp4_dsi_encoder); -} - -static const struct drm_encoder_funcs mdp4_dsi_encoder_funcs = { - .destroy = mdp4_dsi_encoder_destroy, -}; - static void mdp4_dsi_encoder_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) @@ -148,28 +136,18 @@ static const struct drm_encoder_helper_funcs mdp4_dsi_encoder_helper_funcs = { /* initialize encoder */ struct drm_encoder *mdp4_dsi_encoder_init(struct drm_device *dev) { - struct drm_encoder *encoder = NULL; + struct drm_encoder *encoder; struct mdp4_dsi_encoder *mdp4_dsi_encoder; - int ret; - mdp4_dsi_encoder = kzalloc(sizeof(*mdp4_dsi_encoder), GFP_KERNEL); - if (!mdp4_dsi_encoder) { - ret = -ENOMEM; - goto fail; - } + mdp4_dsi_encoder = drmm_encoder_alloc(dev, struct mdp4_dsi_encoder, base, + NULL, DRM_MODE_ENCODER_DSI, NULL); + if (IS_ERR(mdp4_dsi_encoder)) + return ERR_CAST(mdp4_dsi_encoder); encoder = _dsi_encoder->base; - drm_encoder_init(dev, encoder, _dsi_encoder_funcs, -DRM_MODE_ENCODER_DSI, NULL); drm_encoder_helper_add(encoder, _dsi_encoder_helper_funcs); return encoder; - -fail: - if (encoder) - mdp4_dsi_encoder_destroy(encoder); - - return ERR_PTR(ret); } #endif /* CONFIG_DRM_MSM_DSI */ -- 2.39.2
[PATCH 12/17] drm/msm/mdp4: use drmm-managed allocation for mdp4_crtc
Change struct mdp4_crtc allocation to use drmm_crtc_alloc(). This removes the need to perform any actions on CRTC destruction. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/mdp4/mdp4_crtc.c | 33 --- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_crtc.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_crtc.c index 169f9de4a12a..5e5c31b44a8a 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_crtc.c +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_crtc.c @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -123,16 +124,6 @@ static void unref_cursor_worker(struct drm_flip_work *work, void *val) drm_gem_object_put(val); } -static void mdp4_crtc_destroy(struct drm_crtc *crtc) -{ - struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc); - - drm_crtc_cleanup(crtc); - drm_flip_work_cleanup(_crtc->unref_cursor_work); - - kfree(mdp4_crtc); -} - /* statically (for now) map planes to mixer stage (z-order): */ static const int idxs[] = { [VG1] = 1, @@ -475,7 +466,6 @@ static int mdp4_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) static const struct drm_crtc_funcs mdp4_crtc_funcs = { .set_config = drm_atomic_helper_set_config, - .destroy = mdp4_crtc_destroy, .page_flip = drm_atomic_helper_page_flip, .cursor_set = mdp4_crtc_cursor_set, .cursor_move = mdp4_crtc_cursor_move, @@ -616,6 +606,13 @@ static const char *dma_names[] = { "DMA_P", "DMA_S", "DMA_E", }; +static void mdp4_crtc_flip_cleanup(struct drm_device *dev, void *ptr) +{ + struct mdp4_crtc *mdp4_crtc = ptr; + + drm_flip_work_cleanup(_crtc->unref_cursor_work); +} + /* initialize crtc */ struct drm_crtc *mdp4_crtc_init(struct drm_device *dev, struct drm_plane *plane, int id, int ovlp_id, @@ -623,10 +620,13 @@ struct drm_crtc *mdp4_crtc_init(struct drm_device *dev, { struct drm_crtc *crtc = NULL; struct mdp4_crtc *mdp4_crtc; + int ret; - mdp4_crtc = kzalloc(sizeof(*mdp4_crtc), GFP_KERNEL); - if (!mdp4_crtc) - return ERR_PTR(-ENOMEM); + mdp4_crtc = drmm_crtc_alloc_with_planes(dev, struct mdp4_crtc, base, + plane, NULL, + _crtc_funcs, NULL); + if (IS_ERR(mdp4_crtc)) + return ERR_CAST(mdp4_crtc); crtc = _crtc->base; @@ -648,9 +648,10 @@ struct drm_crtc *mdp4_crtc_init(struct drm_device *dev, drm_flip_work_init(_crtc->unref_cursor_work, "unref cursor", unref_cursor_worker); + ret = drmm_add_action_or_reset(dev, mdp4_crtc_flip_cleanup, mdp4_crtc); + if (ret) + return ERR_PTR(ret); - drm_crtc_init_with_planes(dev, crtc, plane, NULL, _crtc_funcs, - NULL); drm_crtc_helper_add(crtc, _crtc_helper_funcs); return crtc; -- 2.39.2
[PATCH 08/17] drm/msm/mdp5: use drmm-managed allocation for mdp5_crtc
Change struct mdp5_crtc allocation to use drmm_crtc_alloc(). This removes the need to perform any actions on CRTC destruction. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c | 30 +++ 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c index 86036dd4e1e8..4a3db2ea1689 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -172,14 +173,11 @@ static void unref_cursor_worker(struct drm_flip_work *work, void *val) drm_gem_object_put(val); } -static void mdp5_crtc_destroy(struct drm_crtc *crtc) +static void mdp5_crtc_flip_cleanup(struct drm_device *dev, void *ptr) { - struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc); + struct mdp5_crtc *mdp5_crtc = ptr; - drm_crtc_cleanup(crtc); drm_flip_work_cleanup(_crtc->unref_cursor_work); - - kfree(mdp5_crtc); } static inline u32 mdp5_lm_use_fg_alpha_mask(enum mdp_mixer_stage_id stage) @@ -1147,7 +1145,6 @@ static void mdp5_crtc_reset(struct drm_crtc *crtc) static const struct drm_crtc_funcs mdp5_crtc_no_lm_cursor_funcs = { .set_config = drm_atomic_helper_set_config, - .destroy = mdp5_crtc_destroy, .page_flip = drm_atomic_helper_page_flip, .reset = mdp5_crtc_reset, .atomic_duplicate_state = mdp5_crtc_duplicate_state, @@ -1161,7 +1158,6 @@ static const struct drm_crtc_funcs mdp5_crtc_no_lm_cursor_funcs = { static const struct drm_crtc_funcs mdp5_crtc_funcs = { .set_config = drm_atomic_helper_set_config, - .destroy = mdp5_crtc_destroy, .page_flip = drm_atomic_helper_page_flip, .reset = mdp5_crtc_reset, .atomic_duplicate_state = mdp5_crtc_duplicate_state, @@ -1327,10 +1323,16 @@ struct drm_crtc *mdp5_crtc_init(struct drm_device *dev, { struct drm_crtc *crtc = NULL; struct mdp5_crtc *mdp5_crtc; + int ret; - mdp5_crtc = kzalloc(sizeof(*mdp5_crtc), GFP_KERNEL); - if (!mdp5_crtc) - return ERR_PTR(-ENOMEM); + mdp5_crtc = drmm_crtc_alloc_with_planes(dev, struct mdp5_crtc, base, + plane, cursor_plane, + cursor_plane ? + _crtc_no_lm_cursor_funcs : + _crtc_funcs, + NULL); + if (IS_ERR(mdp5_crtc)) + return ERR_CAST(mdp5_crtc); crtc = _crtc->base; @@ -1346,13 +1348,11 @@ struct drm_crtc *mdp5_crtc_init(struct drm_device *dev, mdp5_crtc->lm_cursor_enabled = cursor_plane ? false : true; - drm_crtc_init_with_planes(dev, crtc, plane, cursor_plane, - cursor_plane ? - _crtc_no_lm_cursor_funcs : - _crtc_funcs, NULL); - drm_flip_work_init(_crtc->unref_cursor_work, "unref cursor", unref_cursor_worker); + ret = drmm_add_action_or_reset(dev, mdp5_crtc_flip_cleanup, mdp5_crtc); + if (ret) + return ERR_PTR(ret); drm_crtc_helper_add(crtc, _crtc_helper_funcs); -- 2.39.2
[PATCH 10/17] drm/msm/mdp5: use drmm-managed allocation for mdp5_plane
Change struct mdp5_plane allocation to use drmm_plane_alloc(). This removes the need to perform any actions on plane destruction. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c | 40 -- 1 file changed, 6 insertions(+), 34 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c index bd2c4ac45601..177fc1a56aad 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c @@ -17,9 +17,6 @@ struct mdp5_plane { struct drm_plane base; - - uint32_t nformats; - uint32_t formats[32]; }; #define to_mdp5_plane(x) container_of(x, struct mdp5_plane, base) @@ -38,15 +35,6 @@ static bool plane_enabled(struct drm_plane_state *state) return state->visible; } -static void mdp5_plane_destroy(struct drm_plane *plane) -{ - struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane); - - drm_plane_cleanup(plane); - - kfree(mdp5_plane); -} - /* helper to install properties which are common to planes and crtcs */ static void mdp5_plane_install_properties(struct drm_plane *plane, struct drm_mode_object *obj) @@ -139,7 +127,6 @@ static void mdp5_plane_destroy_state(struct drm_plane *plane, static const struct drm_plane_funcs mdp5_plane_funcs = { .update_plane = drm_atomic_helper_update_plane, .disable_plane = drm_atomic_helper_disable_plane, - .destroy = mdp5_plane_destroy, .reset = mdp5_plane_reset, .atomic_duplicate_state = mdp5_plane_duplicate_state, .atomic_destroy_state = mdp5_plane_destroy_state, @@ -1014,25 +1001,16 @@ struct drm_plane *mdp5_plane_init(struct drm_device *dev, { struct drm_plane *plane = NULL; struct mdp5_plane *mdp5_plane; - int ret; - mdp5_plane = kzalloc(sizeof(*mdp5_plane), GFP_KERNEL); - if (!mdp5_plane) { - ret = -ENOMEM; - goto fail; - } + mdp5_plane = drmm_universal_plane_alloc(dev, struct mdp5_plane, base, + 0xff, _plane_funcs, + mdp_rgb_yuv_formats, mdp_rgb_yuv_num_formats, + NULL, type, NULL); + if (IS_ERR(mdp5_plane)) + return ERR_CAST(mdp5_plane); plane = _plane->base; - mdp5_plane->nformats = mdp_get_formats(mdp5_plane->formats, - ARRAY_SIZE(mdp5_plane->formats), false); - - ret = drm_universal_plane_init(dev, plane, 0xff, _plane_funcs, - mdp5_plane->formats, mdp5_plane->nformats, - NULL, type, NULL); - if (ret) - goto fail; - drm_plane_helper_add(plane, _plane_helper_funcs); mdp5_plane_install_properties(plane, >base); @@ -1040,10 +1018,4 @@ struct drm_plane *mdp5_plane_init(struct drm_device *dev, drm_plane_enable_fb_damage_clips(plane); return plane; - -fail: - if (plane) - mdp5_plane_destroy(plane); - - return ERR_PTR(ret); } -- 2.39.2
[PATCH 06/17] drm/msm/mdp5: use devres-managed allocation for SMP data
Use devm_kzalloc to create SMP data structure. This allows us to remove corresponding kfree and drop mdp5_smp_destroy() function. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 3 --- drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c | 19 --- drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.h | 1 - 3 files changed, 4 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c index be4338a48e52..0a85777625d3 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c @@ -618,9 +618,6 @@ static void mdp5_destroy(struct mdp5_kms *mdp5_kms) { int i; - if (mdp5_kms->smp) - mdp5_smp_destroy(mdp5_kms->smp); - for (i = 0; i < mdp5_kms->num_intfs; i++) kfree(mdp5_kms->intfs[i]); diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c index 56a3063545ec..d7c957207255 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c @@ -370,23 +370,17 @@ void mdp5_smp_dump(struct mdp5_smp *smp, struct drm_printer *p) drm_modeset_unlock(_kms->glob_state_lock); } -void mdp5_smp_destroy(struct mdp5_smp *smp) -{ - kfree(smp); -} struct mdp5_smp *mdp5_smp_init(struct mdp5_kms *mdp5_kms, const struct mdp5_smp_block *cfg) { + struct drm_device *dev = mdp5_kms->dev; struct mdp5_smp_state *state; struct mdp5_global_state *global_state; struct mdp5_smp *smp = NULL; - int ret; - smp = kzalloc(sizeof(*smp), GFP_KERNEL); - if (unlikely(!smp)) { - ret = -ENOMEM; - goto fail; - } + smp = devm_kzalloc(dev->dev, sizeof(*smp), GFP_KERNEL); + if (unlikely(!smp)) + return ERR_PTR(-ENOMEM); smp->dev = mdp5_kms->dev; smp->blk_cnt = cfg->mmb_count; @@ -400,9 +394,4 @@ struct mdp5_smp *mdp5_smp_init(struct mdp5_kms *mdp5_kms, const struct mdp5_smp_ memcpy(smp->reserved, cfg->reserved, sizeof(smp->reserved)); return smp; -fail: - if (smp) - mdp5_smp_destroy(smp); - - return ERR_PTR(ret); } diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.h b/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.h index ba5618e136c3..d8b6a11413d9 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.h +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.h @@ -68,7 +68,6 @@ struct mdp5_smp; struct mdp5_smp *mdp5_smp_init(struct mdp5_kms *mdp5_kms, const struct mdp5_smp_block *cfg); -void mdp5_smp_destroy(struct mdp5_smp *smp); void mdp5_smp_dump(struct mdp5_smp *smp, struct drm_printer *p); -- 2.39.2
[PATCH 00/17] drm/msm/mdp[45]: use managed memory allocations
Follow the DPU patchset ([1]) and use devm_ and drmm_ functions to allocate long-living data structures in mdp4 and mdp5 drivers. [1] https://patchwork.freedesktop.org/series/120366/ Dmitry Baryshkov (17): drm/msm: add arrays listing formats supported by MDP4/MDP5 hardware drm/msm/mdp5: use devres-managed allocation for configuration data drm/msm/mdp5: use devres-managed allocation for CTL manager data drm/msm/mdp5: use devres-managed allocation for mixer data drm/msm/mdp5: use devres-managed allocation for pipe data drm/msm/mdp5: use devres-managed allocation for SMP data drm/msm/mdp5: use devres-managed allocation for INTF data drm/msm/mdp5: use drmm-managed allocation for mdp5_crtc drm/msm/mdp5: use drmm-managed allocation for mdp5_encoder drm/msm/mdp5: use drmm-managed allocation for mdp5_plane drm/msm/mdp4: use bulk regulators API for LCDC encoder drm/msm/mdp4: use drmm-managed allocation for mdp4_crtc drm/msm/mdp4: use drmm-managed allocation for mdp4_dsi_encoder drm/msm/mdp4: use drmm-managed allocation for mdp4_dtv_encoder drm/msm/mdp4: use drmm-managed allocation for mdp4_lcdc_encoder drm/msm/mdp4: use drmm-managed allocation for mdp4_plane drm/msm: drop mdp_get_formats() drivers/gpu/drm/msm/disp/mdp4/mdp4_crtc.c | 33 +++ .../gpu/drm/msm/disp/mdp4/mdp4_dsi_encoder.c | 32 ++- .../gpu/drm/msm/disp/mdp4/mdp4_dtv_encoder.c | 37 ++-- .../gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c | 87 +-- drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c| 59 + drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c | 24 ++--- drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.h | 1 - drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c | 30 +++ drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.c | 21 + drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.h | 1 - drivers/gpu/drm/msm/disp/mdp5/mdp5_encoder.c | 29 +-- drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 25 +- drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.c| 10 +-- drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.h| 4 +- drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.c | 10 +-- drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.h | 4 +- drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c| 40 ++--- drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c | 19 +--- drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.h | 1 - drivers/gpu/drm/msm/disp/mdp_format.c | 67 +- drivers/gpu/drm/msm/disp/mdp_kms.h| 6 +- 21 files changed, 171 insertions(+), 369 deletions(-) -- 2.39.2
[PATCH 05/17] drm/msm/mdp5: use devres-managed allocation for pipe data
Use devm_kzalloc to create pipe data structure. This allows us to remove corresponding kfree and drop mdp5_pipe_destroy() function. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 6 +- drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.c | 10 +++--- drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.h | 4 ++-- 3 files changed, 6 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c index b4a49d369f0d..be4338a48e52 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c @@ -209,10 +209,6 @@ static void mdp5_kms_destroy(struct msm_kms *kms) { struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms)); struct msm_gem_address_space *aspace = kms->aspace; - int i; - - for (i = 0; i < mdp5_kms->num_hwpipes; i++) - mdp5_pipe_destroy(mdp5_kms->hwpipes[i]); if (aspace) { aspace->mmu->funcs->detach(aspace->mmu); @@ -645,7 +641,7 @@ static int construct_pipes(struct mdp5_kms *mdp5_kms, int cnt, for (i = 0; i < cnt; i++) { struct mdp5_hw_pipe *hwpipe; - hwpipe = mdp5_pipe_init(pipes[i], offsets[i], caps); + hwpipe = mdp5_pipe_init(dev, pipes[i], offsets[i], caps); if (IS_ERR(hwpipe)) { ret = PTR_ERR(hwpipe); DRM_DEV_ERROR(dev->dev, "failed to construct pipe for %s (%d)\n", diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.c index e4b8a789835a..99b2c30b1d48 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.c @@ -151,17 +151,13 @@ int mdp5_pipe_release(struct drm_atomic_state *s, struct mdp5_hw_pipe *hwpipe) return 0; } -void mdp5_pipe_destroy(struct mdp5_hw_pipe *hwpipe) -{ - kfree(hwpipe); -} - -struct mdp5_hw_pipe *mdp5_pipe_init(enum mdp5_pipe pipe, +struct mdp5_hw_pipe *mdp5_pipe_init(struct drm_device *dev, + enum mdp5_pipe pipe, uint32_t reg_offset, uint32_t caps) { struct mdp5_hw_pipe *hwpipe; - hwpipe = kzalloc(sizeof(*hwpipe), GFP_KERNEL); + hwpipe = devm_kzalloc(dev->dev, sizeof(*hwpipe), GFP_KERNEL); if (!hwpipe) return ERR_PTR(-ENOMEM); diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.h b/drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.h index cca67938cab2..452138821f60 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.h +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.h @@ -39,8 +39,8 @@ int mdp5_pipe_assign(struct drm_atomic_state *s, struct drm_plane *plane, struct mdp5_hw_pipe **r_hwpipe); int mdp5_pipe_release(struct drm_atomic_state *s, struct mdp5_hw_pipe *hwpipe); -struct mdp5_hw_pipe *mdp5_pipe_init(enum mdp5_pipe pipe, +struct mdp5_hw_pipe *mdp5_pipe_init(struct drm_device *dev, + enum mdp5_pipe pipe, uint32_t reg_offset, uint32_t caps); -void mdp5_pipe_destroy(struct mdp5_hw_pipe *hwpipe); #endif /* __MDP5_PIPE_H__ */ -- 2.39.2
[PATCH 07/17] drm/msm/mdp5: use devres-managed allocation for INTF data
Use devm_kzalloc to create INTF data structure. This allows us to remove corresponding kfree() call. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 7 +-- 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c index 0a85777625d3..fb2b3bf081ee 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c @@ -616,11 +616,6 @@ static int mdp5_kms_init(struct drm_device *dev) static void mdp5_destroy(struct mdp5_kms *mdp5_kms) { - int i; - - for (i = 0; i < mdp5_kms->num_intfs; i++) - kfree(mdp5_kms->intfs[i]); - if (mdp5_kms->rpm_enabled) pm_runtime_disable(_kms->pdev->dev); @@ -741,7 +736,7 @@ static int interface_init(struct mdp5_kms *mdp5_kms) if (intf_types[i] == INTF_DISABLED) continue; - intf = kzalloc(sizeof(*intf), GFP_KERNEL); + intf = devm_kzalloc(dev->dev, sizeof(*intf), GFP_KERNEL); if (!intf) { DRM_DEV_ERROR(dev->dev, "failed to construct INTF%d\n", i); return -ENOMEM; -- 2.39.2
[PATCH 01/17] drm/msm: add arrays listing formats supported by MDP4/MDP5 hardware
MDP4 and MDP5 drivers enumerate supported formats each time the plane is created. As the list of supported image formats is constant, create corresponding data arrays to be used by MDP4 and MDP5 drivers. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/mdp_format.c | 49 +-- drivers/gpu/drm/msm/disp/mdp_kms.h| 5 +++ 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/mdp_format.c b/drivers/gpu/drm/msm/disp/mdp_format.c index 025595336f26..ba9abe8b3acc 100644 --- a/drivers/gpu/drm/msm/disp/mdp_format.c +++ b/drivers/gpu/drm/msm/disp/mdp_format.c @@ -81,8 +81,8 @@ static struct csc_cfg csc_convert[CSC_MAX] = { #define BPC0A 0 /* - * Note: Keep RGB formats 1st, followed by YUV formats to avoid breaking - * mdp_get_rgb_formats()'s implementation. + * Note: Keep mdp_rgb_formats and mdp_rgb_yuv_formats in sync when adding + * entries to this array. */ static const struct mdp_format formats[] = { /* name a r g b e0 e1 e2 e3 alpha tight cpp cnt ... */ @@ -138,6 +138,51 @@ static const struct mdp_format formats[] = { MDP_PLANE_PLANAR, CHROMA_420, true), }; +const uint32_t mdp_rgb_formats[] = { + DRM_FORMAT_ARGB, + DRM_FORMAT_ABGR, + DRM_FORMAT_RGBA, + DRM_FORMAT_BGRA, + DRM_FORMAT_XRGB, + DRM_FORMAT_XBGR, + DRM_FORMAT_RGBX, + DRM_FORMAT_BGRX, + DRM_FORMAT_RGB888, + DRM_FORMAT_BGR888, + DRM_FORMAT_RGB565, + DRM_FORMAT_BGR565, +}; + +size_t mdp_rgb_num_formats = ARRAY_SIZE(mdp_rgb_formats); + +const uint32_t mdp_rgb_yuv_formats[] = { + DRM_FORMAT_ARGB, + DRM_FORMAT_ABGR, + DRM_FORMAT_RGBA, + DRM_FORMAT_BGRA, + DRM_FORMAT_XRGB, + DRM_FORMAT_XBGR, + DRM_FORMAT_RGBX, + DRM_FORMAT_BGRX, + DRM_FORMAT_RGB888, + DRM_FORMAT_BGR888, + DRM_FORMAT_RGB565, + DRM_FORMAT_BGR565, + + DRM_FORMAT_NV12, + DRM_FORMAT_NV21, + DRM_FORMAT_NV16, + DRM_FORMAT_NV61, + DRM_FORMAT_VYUY, + DRM_FORMAT_UYVY, + DRM_FORMAT_YUYV, + DRM_FORMAT_YVYU, + DRM_FORMAT_YUV420, + DRM_FORMAT_YVU420, +}; + +size_t mdp_rgb_yuv_num_formats = ARRAY_SIZE(mdp_rgb_yuv_formats); + /* * Note: * @rgb_only must be set to true, when requesting diff --git a/drivers/gpu/drm/msm/disp/mdp_kms.h b/drivers/gpu/drm/msm/disp/mdp_kms.h index b0286d5d5130..11402a859574 100644 --- a/drivers/gpu/drm/msm/disp/mdp_kms.h +++ b/drivers/gpu/drm/msm/disp/mdp_kms.h @@ -94,6 +94,11 @@ struct mdp_format { uint32_t mdp_get_formats(uint32_t *formats, uint32_t max_formats, bool rgb_only); const struct msm_format *mdp_get_format(struct msm_kms *kms, uint32_t format, uint64_t modifier); +extern const uint32_t mdp_rgb_formats[]; +extern size_t mdp_rgb_num_formats; +extern const uint32_t mdp_rgb_yuv_formats[]; +extern size_t mdp_rgb_yuv_num_formats; + /* MDP capabilities */ #define MDP_CAP_SMPBIT(0) /* Shared Memory Pool */ #define MDP_CAP_DSCBIT(1) /* VESA Display Stream Compression*/ -- 2.39.2
[PATCH 03/17] drm/msm/mdp5: use devres-managed allocation for CTL manager data
Use devm_kzalloc to create CTL manager data structure. This allows us to remove corresponding kfree and drop mdp5_ctlm_destroy() function. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.c | 21 - drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.h | 1 - drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 2 -- 3 files changed, 4 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.c index 1220f2b20e05..666de99a46a5 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.c @@ -681,11 +681,6 @@ void mdp5_ctlm_hw_reset(struct mdp5_ctl_manager *ctl_mgr) } } -void mdp5_ctlm_destroy(struct mdp5_ctl_manager *ctl_mgr) -{ - kfree(ctl_mgr); -} - struct mdp5_ctl_manager *mdp5_ctlm_init(struct drm_device *dev, void __iomem *mmio_base, struct mdp5_cfg_handler *cfg_hnd) { @@ -697,18 +692,16 @@ struct mdp5_ctl_manager *mdp5_ctlm_init(struct drm_device *dev, unsigned long flags; int c, ret; - ctl_mgr = kzalloc(sizeof(*ctl_mgr), GFP_KERNEL); + ctl_mgr = devm_kzalloc(dev->dev, sizeof(*ctl_mgr), GFP_KERNEL); if (!ctl_mgr) { DRM_DEV_ERROR(dev->dev, "failed to allocate CTL manager\n"); - ret = -ENOMEM; - goto fail; + return ERR_PTR(-ENOMEM); } if (WARN_ON(ctl_cfg->count > MAX_CTL)) { DRM_DEV_ERROR(dev->dev, "Increase static pool size to at least %d\n", ctl_cfg->count); - ret = -ENOSPC; - goto fail; + return ERR_PTR(-ENOSPC); } /* initialize the CTL manager: */ @@ -727,7 +720,7 @@ struct mdp5_ctl_manager *mdp5_ctlm_init(struct drm_device *dev, DRM_DEV_ERROR(dev->dev, "CTL_%d: base is null!\n", c); ret = -EINVAL; spin_unlock_irqrestore(_mgr->pool_lock, flags); - goto fail; + return ERR_PTR(ret); } ctl->ctlm = ctl_mgr; ctl->id = c; @@ -755,10 +748,4 @@ struct mdp5_ctl_manager *mdp5_ctlm_init(struct drm_device *dev, DBG("Pool of %d CTLs created.", ctl_mgr->nctl); return ctl_mgr; - -fail: - if (ctl_mgr) - mdp5_ctlm_destroy(ctl_mgr); - - return ERR_PTR(ret); } diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.h b/drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.h index c2af68aa77ae..9020e8efc4e4 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.h +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.h @@ -17,7 +17,6 @@ struct mdp5_ctl_manager; struct mdp5_ctl_manager *mdp5_ctlm_init(struct drm_device *dev, void __iomem *mmio_base, struct mdp5_cfg_handler *cfg_hnd); void mdp5_ctlm_hw_reset(struct mdp5_ctl_manager *ctlm); -void mdp5_ctlm_destroy(struct mdp5_ctl_manager *ctlm); /* * CTL prototypes: diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c index 828634206185..e20ead138602 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c @@ -625,8 +625,6 @@ static void mdp5_destroy(struct mdp5_kms *mdp5_kms) { int i; - if (mdp5_kms->ctlm) - mdp5_ctlm_destroy(mdp5_kms->ctlm); if (mdp5_kms->smp) mdp5_smp_destroy(mdp5_kms->smp); -- 2.39.2
[PATCH 04/17] drm/msm/mdp5: use devres-managed allocation for mixer data
Use devm_kzalloc to create mixer data structure. This allows us to remove corresponding kfree and drop mdp5_mixer_destroy() function. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 5 + drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.c | 10 +++--- drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.h | 4 ++-- 3 files changed, 6 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c index e20ead138602..b4a49d369f0d 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c @@ -211,9 +211,6 @@ static void mdp5_kms_destroy(struct msm_kms *kms) struct msm_gem_address_space *aspace = kms->aspace; int i; - for (i = 0; i < mdp5_kms->num_hwmixers; i++) - mdp5_mixer_destroy(mdp5_kms->hwmixers[i]); - for (i = 0; i < mdp5_kms->num_hwpipes; i++) mdp5_pipe_destroy(mdp5_kms->hwpipes[i]); @@ -720,7 +717,7 @@ static int hwmixer_init(struct mdp5_kms *mdp5_kms) for (i = 0; i < hw_cfg->lm.count; i++) { struct mdp5_hw_mixer *mixer; - mixer = mdp5_mixer_init(_cfg->lm.instances[i]); + mixer = mdp5_mixer_init(dev, _cfg->lm.instances[i]); if (IS_ERR(mixer)) { ret = PTR_ERR(mixer); DRM_DEV_ERROR(dev->dev, "failed to construct LM%d (%d)\n", diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.c index 2536def2a000..2822b533f807 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.c @@ -140,20 +140,16 @@ int mdp5_mixer_release(struct drm_atomic_state *s, struct mdp5_hw_mixer *mixer) return 0; } -void mdp5_mixer_destroy(struct mdp5_hw_mixer *mixer) -{ - kfree(mixer); -} - static const char * const mixer_names[] = { "LM0", "LM1", "LM2", "LM3", "LM4", "LM5", }; -struct mdp5_hw_mixer *mdp5_mixer_init(const struct mdp5_lm_instance *lm) +struct mdp5_hw_mixer *mdp5_mixer_init(struct drm_device *dev, + const struct mdp5_lm_instance *lm) { struct mdp5_hw_mixer *mixer; - mixer = kzalloc(sizeof(*mixer), GFP_KERNEL); + mixer = devm_kzalloc(dev->dev, sizeof(*mixer), GFP_KERNEL); if (!mixer) return ERR_PTR(-ENOMEM); diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.h b/drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.h index 545ee223b9d7..2bedd75835bc 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.h +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.h @@ -25,8 +25,8 @@ struct mdp5_hw_mixer_state { struct drm_crtc *hwmixer_to_crtc[8]; }; -struct mdp5_hw_mixer *mdp5_mixer_init(const struct mdp5_lm_instance *lm); -void mdp5_mixer_destroy(struct mdp5_hw_mixer *lm); +struct mdp5_hw_mixer *mdp5_mixer_init(struct drm_device *dev, + const struct mdp5_lm_instance *lm); int mdp5_mixer_assign(struct drm_atomic_state *s, struct drm_crtc *crtc, uint32_t caps, struct mdp5_hw_mixer **mixer, struct mdp5_hw_mixer **r_mixer); -- 2.39.2
[PATCH 02/17] drm/msm/mdp5: use devres-managed allocation for configuration data
Use devm_kzalloc to create configuration data structure. This allows us to remove corresponding kfree and drop mdp5_cfg_destroy() function. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c | 24 +--- drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.h | 1 - drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 2 -- 3 files changed, 5 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c index 694d54341337..c5179e4c393c 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c @@ -1350,23 +1350,17 @@ int mdp5_cfg_get_hw_rev(struct mdp5_cfg_handler *cfg_handler) return cfg_handler->revision; } -void mdp5_cfg_destroy(struct mdp5_cfg_handler *cfg_handler) -{ - kfree(cfg_handler); -} - struct mdp5_cfg_handler *mdp5_cfg_init(struct mdp5_kms *mdp5_kms, uint32_t major, uint32_t minor) { struct drm_device *dev = mdp5_kms->dev; struct mdp5_cfg_handler *cfg_handler; const struct mdp5_cfg_handler *cfg_handlers; - int i, ret = 0, num_handlers; + int i, num_handlers; - cfg_handler = kzalloc(sizeof(*cfg_handler), GFP_KERNEL); + cfg_handler = devm_kzalloc(dev->dev, sizeof(*cfg_handler), GFP_KERNEL); if (unlikely(!cfg_handler)) { - ret = -ENOMEM; - goto fail; + return ERR_PTR(-ENOMEM); } switch (major) { @@ -1381,8 +1375,7 @@ struct mdp5_cfg_handler *mdp5_cfg_init(struct mdp5_kms *mdp5_kms, default: DRM_DEV_ERROR(dev->dev, "unexpected MDP major version: v%d.%d\n", major, minor); - ret = -ENXIO; - goto fail; + return ERR_PTR(-ENXIO); } /* only after mdp5_cfg global pointer's init can we access the hw */ @@ -1396,8 +1389,7 @@ struct mdp5_cfg_handler *mdp5_cfg_init(struct mdp5_kms *mdp5_kms, if (unlikely(!mdp5_cfg)) { DRM_DEV_ERROR(dev->dev, "unexpected MDP minor revision: v%d.%d\n", major, minor); - ret = -ENXIO; - goto fail; + return ERR_PTR(-ENXIO); } cfg_handler->revision = minor; @@ -1406,10 +1398,4 @@ struct mdp5_cfg_handler *mdp5_cfg_init(struct mdp5_kms *mdp5_kms, DBG("MDP5: %s hw config selected", mdp5_cfg->name); return cfg_handler; - -fail: - if (cfg_handler) - mdp5_cfg_destroy(cfg_handler); - - return ERR_PTR(ret); } diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.h b/drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.h index c2502cc33864..26c5d8b4ab46 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.h +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.h @@ -121,6 +121,5 @@ int mdp5_cfg_get_hw_rev(struct mdp5_cfg_handler *cfg_hnd); struct mdp5_cfg_handler *mdp5_cfg_init(struct mdp5_kms *mdp5_kms, uint32_t major, uint32_t minor); -void mdp5_cfg_destroy(struct mdp5_cfg_handler *cfg_hnd); #endif /* __MDP5_CFG_H__ */ diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c index 52f176e08690..828634206185 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c @@ -629,8 +629,6 @@ static void mdp5_destroy(struct mdp5_kms *mdp5_kms) mdp5_ctlm_destroy(mdp5_kms->ctlm); if (mdp5_kms->smp) mdp5_smp_destroy(mdp5_kms->smp); - if (mdp5_kms->cfg) - mdp5_cfg_destroy(mdp5_kms->cfg); for (i = 0; i < mdp5_kms->num_intfs; i++) kfree(mdp5_kms->intfs[i]); -- 2.39.2
Re: [PATCH v1 0/5] incorporate pm runtime framework and eDP clean up
On 08/07/2023 02:52, Kuogee Hsieh wrote: Incorporate pm runtime framework into DP driver and clean up eDP by moving of_dp_aux_populate_bus() to probe() Please use sensible prefix for cover letters too. It helps people understand, which driver/area is touched by the patchset. Kuogee Hsieh (5): drm/msm/dp: remove pm_runtime_xxx() from dp_power.c drm/msm/dp: incorporate pm_runtime framework into DP driver drm/msm/dp: delete EV_HPD_INIT_SETUP drm/msm/dp: move relevant dp initialization code from bind() to probe() drm/msm/dp: move of_dp_aux_populate_bus() to probe for eDP drivers/gpu/drm/msm/dp/dp_aux.c | 28 + drivers/gpu/drm/msm/dp/dp_display.c | 204 +--- drivers/gpu/drm/msm/dp/dp_display.h | 1 - drivers/gpu/drm/msm/dp/dp_power.c | 9 -- 4 files changed, 145 insertions(+), 97 deletions(-) -- With best wishes Dmitry
Re: [PATCH v1 3/5] drm/msm/dp: delete EV_HPD_INIT_SETUP
On 08/07/2023 02:52, Kuogee Hsieh wrote: EV_HPD_INIT_SETUP flag is used to trigger the initialization of external DP host controller. Since external DP host controller initialization had been incorporated into pm_runtime_resume(), this flag become obsolete. Lets get rid of it. And another question. Between patches #2 and #3 we have both INIT_SETUP event and the PM doing dp_display_host_init(). Will it work correctly? Signed-off-by: Kuogee Hsieh --- drivers/gpu/drm/msm/dp/dp_display.c | 12 1 file changed, 12 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 2c5706a..44580c2 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -55,7 +55,6 @@ enum { enum { EV_NO_EVENT, /* hpd events */ - EV_HPD_INIT_SETUP, EV_HPD_PLUG_INT, EV_IRQ_HPD_INT, EV_HPD_UNPLUG_INT, @@ -1119,9 +1118,6 @@ static int hpd_event_thread(void *data) spin_unlock_irqrestore(_priv->event_lock, flag); switch (todo->event_id) { - case EV_HPD_INIT_SETUP: - dp_display_host_init(dp_priv); - break; case EV_HPD_PLUG_INT: dp_hpd_plug_handle(dp_priv, todo->data); break; @@ -1483,15 +1479,7 @@ void __exit msm_dp_unregister(void) void msm_dp_irq_postinstall(struct msm_dp *dp_display) { - struct dp_display_private *dp; - - if (!dp_display) - return; - - dp = container_of(dp_display, struct dp_display_private, dp_display); - if (!dp_display->is_edp) - dp_add_event(dp, EV_HPD_INIT_SETUP, 0, 0); } bool msm_dp_wide_bus_available(const struct msm_dp *dp_display) -- With best wishes Dmitry
Re: [PATCH v1 5/5] drm/msm/dp: move of_dp_aux_populate_bus() to probe for eDP
On 08/07/2023 02:52, Kuogee Hsieh wrote: Move of_dp_aux_populate_bus() to dp_display_probe() for eDP from dp_display_bind() so that probe deferral cases can be handled effectively Signed-off-by: Kuogee Hsieh --- drivers/gpu/drm/msm/dp/dp_aux.c | 25 drivers/gpu/drm/msm/dp/dp_display.c | 79 +++-- 2 files changed, 65 insertions(+), 39 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_aux.c b/drivers/gpu/drm/msm/dp/dp_aux.c index c592064..c1baffb 100644 --- a/drivers/gpu/drm/msm/dp/dp_aux.c +++ b/drivers/gpu/drm/msm/dp/dp_aux.c @@ -505,6 +505,21 @@ void dp_aux_unregister(struct drm_dp_aux *dp_aux) drm_dp_aux_unregister(dp_aux); } +static int dp_wait_hpd_asserted(struct drm_dp_aux *dp_aux, +unsigned long wait_us) +{ + int ret; + struct dp_aux_private *aux; + + aux = container_of(dp_aux, struct dp_aux_private, dp_aux); + + pm_runtime_get_sync(aux->dev); + ret = dp_catalog_aux_wait_for_hpd_connect_state(aux->catalog); + pm_runtime_put_sync(aux->dev); + + return ret; +} + struct drm_dp_aux *dp_aux_get(struct device *dev, struct dp_catalog *catalog, bool is_edp) { @@ -528,6 +543,16 @@ struct drm_dp_aux *dp_aux_get(struct device *dev, struct dp_catalog *catalog, aux->catalog = catalog; aux->retry_cnt = 0; + /* +* Use the drm_dp_aux_init() to use the aux adapter +* before registering aux with the DRM device. +*/ + aux->dp_aux.name = "dpu_dp_aux"; + aux->dp_aux.dev = dev; + aux->dp_aux.transfer = dp_aux_transfer; + aux->dp_aux.wait_hpd_asserted = dp_wait_hpd_asserted; + drm_dp_aux_init(>dp_aux); + return >dp_aux; } diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 185f1eb..7ed4bea 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -302,10 +302,6 @@ static int dp_display_bind(struct device *dev, struct device *master, goto end; } - pm_runtime_enable(dev); - pm_runtime_set_autosuspend_delay(dev, 1000); - pm_runtime_use_autosuspend(dev); - return 0; end: return rc; @@ -322,8 +318,6 @@ static void dp_display_unbind(struct device *dev, struct device *master, kthread_stop(dp->ev_tsk); - of_dp_aux_depopulate_bus(dp->aux); - dp_power_client_deinit(dp->power); dp_unregister_audio_driver(dev, dp->audio); dp_aux_unregister(dp->aux); @@ -1245,6 +1239,29 @@ static const struct msm_dp_desc *dp_display_get_desc(struct platform_device *pde return NULL; } +static void of_dp_aux_depopulate_bus_void(void *data) +{ + of_dp_aux_depopulate_bus(data); +} + +static int dp_display_auxbus_emulation(struct dp_display_private *dp) Why is it called emulation? +{ + struct device *dev = >pdev->dev; + struct device_node *aux_bus; + int ret = 0; + + aux_bus = of_get_child_by_name(dev->of_node, "aux-bus"); + + if (aux_bus) { + ret = devm_of_dp_aux_populate_bus(dp->aux, NULL); And here you missed the whole point of why we have been asking for. Please add a sensible `done_probing' callback, which will call component_add(). This way the DP component will only be registered when the panel has been probed. Keeping us from the component binding retries and corresponding side effects. + + devm_add_action_or_reset(dev, of_dp_aux_depopulate_bus_void, +dp->aux); Useless, it's already handled by the devm_ part of the devm_of_dp_aux_populate_bus(). + } + + return ret; +} + static int dp_display_probe(struct platform_device *pdev) { int rc = 0; @@ -1290,8 +1307,18 @@ static int dp_display_probe(struct platform_device *pdev) platform_set_drvdata(pdev, >dp_display); + pm_runtime_enable(>dev); + pm_runtime_set_autosuspend_delay(>dev, 1000); + pm_runtime_use_autosuspend(>dev); Can we have this in probe right from the patch #2? + dp_display_request_irq(dp); + if (dp->dp_display.is_edp) { + rc = dp_display_auxbus_emulation(dp); + if (rc) + DRM_ERROR("eDP aux-bus emulation failed, rc=%d\n", rc); + } + rc = component_add(>dev, _display_comp_ops); if (rc) { DRM_ERROR("component add failed, rc=%d\n", rc); @@ -1306,11 +1333,14 @@ static int dp_display_remove(struct platform_device *pdev) struct dp_display_private *dp = dev_get_dp_display_private(>dev); component_del(>dev, _display_comp_ops); - dp_display_deinit_sub_modules(dp); - platform_set_drvdata(pdev, NULL); + + pm_runtime_dont_use_autosuspend(>dev); + pm_runtime_disable(>dev); pm_runtime_put_sync_suspend(>dev); +
Re: [PATCH v1 4/5] drm/msm/dp: move relevant dp initialization code from bind() to probe()
On 08/07/2023 02:52, Kuogee Hsieh wrote: In preparation of moving edp of_dp_aux_populate_bus() to dp_display_probe(), move dp_display_request_irq(), dp->parser->parse() and dp_power_client_init() to dp_display_probe() too. Signed-off-by: Kuogee Hsieh --- drivers/gpu/drm/msm/dp/dp_display.c | 48 + drivers/gpu/drm/msm/dp/dp_display.h | 1 - 2 files changed, 22 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 44580c2..185f1eb 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -290,12 +290,6 @@ static int dp_display_bind(struct device *dev, struct device *master, goto end; } - rc = dp_power_client_init(dp->power); - if (rc) { - DRM_ERROR("Power client create failed\n"); - goto end; - } - rc = dp_register_audio_driver(dev, dp->audio); if (rc) { DRM_ERROR("Audio registration Dp failed\n"); @@ -752,6 +746,12 @@ static int dp_init_sub_modules(struct dp_display_private *dp) goto error; } + rc = dp->parser->parse(dp->parser); + if (rc) { + DRM_ERROR("device tree parsing failed\n"); + goto error; + } + dp->catalog = dp_catalog_get(dev, >parser->io); if (IS_ERR(dp->catalog)) { rc = PTR_ERR(dp->catalog); @@ -768,6 +768,12 @@ static int dp_init_sub_modules(struct dp_display_private *dp) goto error; } + rc = dp_power_client_init(dp->power); + if (rc) { + DRM_ERROR("Power client create failed\n"); + goto error; + } + dp->aux = dp_aux_get(dev, dp->catalog, dp->dp_display.is_edp); if (IS_ERR(dp->aux)) { rc = PTR_ERR(dp->aux); @@ -1196,26 +1202,20 @@ static irqreturn_t dp_display_irq_handler(int irq, void *dev_id) return ret; } -int dp_display_request_irq(struct msm_dp *dp_display) +static int dp_display_request_irq(struct dp_display_private *dp) { int rc = 0; - struct dp_display_private *dp; - - if (!dp_display) { - DRM_ERROR("invalid input\n"); - return -EINVAL; - } - - dp = container_of(dp_display, struct dp_display_private, dp_display); + struct device *dev = >pdev->dev; - dp->irq = irq_of_parse_and_map(dp->pdev->dev.of_node, 0); if (!dp->irq) { - DRM_ERROR("failed to get irq\n"); - return -EINVAL; + dp->irq = irq_of_parse_and_map(dp->pdev->dev.of_node, 0); + if (!dp->irq) { + DRM_ERROR("failed to get irq\n"); + return -EINVAL; + } } Use platform_get_irq() from probe() function. - rc = devm_request_irq(dp_display->drm_dev->dev, dp->irq, - dp_display_irq_handler, + rc = devm_request_irq(dev, dp->irq, dp_display_irq_handler, IRQF_TRIGGER_HIGH, "dp_display_isr", dp); if (rc < 0) { DRM_ERROR("failed to request IRQ%u: %d\n", @@ -1290,6 +1290,8 @@ static int dp_display_probe(struct platform_device *pdev) platform_set_drvdata(pdev, >dp_display); + dp_display_request_irq(dp); + Error checking? Are we completely ready to handle interrupts at this point? rc = component_add(>dev, _display_comp_ops); if (rc) { DRM_ERROR("component add failed, rc=%d\n", rc); @@ -1574,12 +1576,6 @@ int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev, dp_priv = container_of(dp_display, struct dp_display_private, dp_display); - ret = dp_display_request_irq(dp_display); - if (ret) { - DRM_ERROR("request_irq failed, ret=%d\n", ret); - return ret; - } - ret = dp_display_get_next_bridge(dp_display); if (ret) return ret; diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h index 1e9415a..b3c08de 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.h +++ b/drivers/gpu/drm/msm/dp/dp_display.h @@ -35,7 +35,6 @@ struct msm_dp { int dp_display_set_plugged_cb(struct msm_dp *dp_display, hdmi_codec_plugged_cb fn, struct device *codec_dev); int dp_display_get_modes(struct msm_dp *dp_display); -int dp_display_request_irq(struct msm_dp *dp_display); bool dp_display_check_video_test(struct msm_dp *dp_display); int dp_display_get_test_bpp(struct msm_dp *dp_display); void dp_display_signal_audio_start(struct msm_dp *dp_display); -- With best wishes Dmitry
Re: [PATCH v1 3/5] drm/msm/dp: delete EV_HPD_INIT_SETUP
On 08/07/2023 02:52, Kuogee Hsieh wrote: EV_HPD_INIT_SETUP flag is used to trigger the initialization of external DP host controller. Since external DP host controller initialization had been incorporated into pm_runtime_resume(), this flag become obsolete. Lets get rid of it. Signed-off-by: Kuogee Hsieh --- drivers/gpu/drm/msm/dp/dp_display.c | 12 1 file changed, 12 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 2c5706a..44580c2 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -55,7 +55,6 @@ enum { enum { EV_NO_EVENT, /* hpd events */ - EV_HPD_INIT_SETUP, EV_HPD_PLUG_INT, EV_IRQ_HPD_INT, EV_HPD_UNPLUG_INT, @@ -1119,9 +1118,6 @@ static int hpd_event_thread(void *data) spin_unlock_irqrestore(_priv->event_lock, flag); switch (todo->event_id) { - case EV_HPD_INIT_SETUP: - dp_display_host_init(dp_priv); - break; case EV_HPD_PLUG_INT: dp_hpd_plug_handle(dp_priv, todo->data); break; @@ -1483,15 +1479,7 @@ void __exit msm_dp_unregister(void) void msm_dp_irq_postinstall(struct msm_dp *dp_display) { - struct dp_display_private *dp; - - if (!dp_display) - return; - - dp = container_of(dp_display, struct dp_display_private, dp_display); - if (!dp_display->is_edp) - dp_add_event(dp, EV_HPD_INIT_SETUP, 0, 0); } Why do you keep an empty function? bool msm_dp_wide_bus_available(const struct msm_dp *dp_display) -- With best wishes Dmitry
Re: [PATCH] drm/nouveau/disp/g94: enable HDMI
On Fri, Jul 7, 2023 at 11:03 PM Lyude Paul wrote: > > Reviewed-by: Lyude Paul > > But seeing as I looked at this + some other patches yesterday I assume there's > still more to this? > not really. All those patches are all independent and just a bunch of fixes. I just figured this one out a bit later. > On Fri, 2023-06-30 at 18:06 +0200, Karol Herbst wrote: > > Cc: Ben Skeggs > > Cc: Lyude Paul > > Fixes: f530bc60a30b ("drm/nouveau/disp: move HDMI config into acquire + > > infoframe methods") > > Signed-off-by: Karol Herbst > > --- > > drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c | 1 + > > 1 file changed, 1 insertion(+) > > > > diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c > > b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c > > index a4853c4e5ee3..67ef889a0c5f 100644 > > --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c > > +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c > > @@ -295,6 +295,7 @@ g94_sor = { > > .clock = nv50_sor_clock, > > .war_2 = g94_sor_war_2, > > .war_3 = g94_sor_war_3, > > + .hdmi = _sor_hdmi, > > .dp = _sor_dp, > > }; > > > > -- > Cheers, > Lyude Paul (she/her) > Software Engineer at Red Hat >
Re: [PATCH v1 1/5] drm/msm/dp: remove pm_runtime_xxx() from dp_power.c
On 08/07/2023 02:52, Kuogee Hsieh wrote: Since both pm_runtime_resume() and pm_runtime_suspend() are not populated at dp_pm_ops. Those pm_runtime_get/put() functions within dp_power.c will not have any effects in addition to increase/decrease power counter. Lie. Also pm_runtime_xxx() should be executed at top layer. Why? Signed-off-by: Kuogee Hsieh --- drivers/gpu/drm/msm/dp/dp_power.c | 9 - 1 file changed, 9 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_power.c b/drivers/gpu/drm/msm/dp/dp_power.c index 5cb84ca..ed2f62a 100644 --- a/drivers/gpu/drm/msm/dp/dp_power.c +++ b/drivers/gpu/drm/msm/dp/dp_power.c @@ -152,8 +152,6 @@ int dp_power_client_init(struct dp_power *dp_power) power = container_of(dp_power, struct dp_power_private, dp_power); - pm_runtime_enable(power->dev); - return dp_power_clk_init(power); } @@ -162,8 +160,6 @@ void dp_power_client_deinit(struct dp_power *dp_power) struct dp_power_private *power; power = container_of(dp_power, struct dp_power_private, dp_power); - - pm_runtime_disable(power->dev); } int dp_power_init(struct dp_power *dp_power) @@ -173,11 +169,7 @@ int dp_power_init(struct dp_power *dp_power) power = container_of(dp_power, struct dp_power_private, dp_power); - pm_runtime_get_sync(power->dev); - rc = dp_power_clk_enable(dp_power, DP_CORE_PM, true); - if (rc) - pm_runtime_put_sync(power->dev); return rc; } @@ -189,7 +181,6 @@ int dp_power_deinit(struct dp_power *dp_power) power = container_of(dp_power, struct dp_power_private, dp_power); dp_power_clk_enable(dp_power, DP_CORE_PM, false); - pm_runtime_put_sync(power->dev); return 0; } -- With best wishes Dmitry
Re: [PATCH v1 2/5] drm/msm/dp: incorporate pm_runtime framework into DP driver
On 08/07/2023 02:52, Kuogee Hsieh wrote: Incorporating pm runtime framework into DP driver so that power and clock resource handling can be centralized allowing easier control of these resources in preparation of registering aux bus uring probe. Signed-off-by: Kuogee Hsieh --- drivers/gpu/drm/msm/dp/dp_aux.c | 3 ++ drivers/gpu/drm/msm/dp/dp_display.c | 75 + 2 files changed, 63 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_aux.c b/drivers/gpu/drm/msm/dp/dp_aux.c index 8e3b677..c592064 100644 --- a/drivers/gpu/drm/msm/dp/dp_aux.c +++ b/drivers/gpu/drm/msm/dp/dp_aux.c @@ -291,6 +291,7 @@ static ssize_t dp_aux_transfer(struct drm_dp_aux *dp_aux, return -EINVAL; } + pm_runtime_get_sync(dp_aux->dev); Let me quote the function's documentation: Consider using pm_runtime_resume_and_get() instead of it, especially if its return value is checked by the caller, as this is likely to result in cleaner code. So two notes concerning the whole patch: - error checking is missing - please use pm_runtime_resume_and_get() instead. mutex_lock(>mutex); if (!aux->initted) { ret = -EIO; @@ -364,6 +365,8 @@ static ssize_t dp_aux_transfer(struct drm_dp_aux *dp_aux, exit: mutex_unlock(>mutex); + pm_runtime_mark_last_busy(dp_aux->dev); + pm_runtime_put_autosuspend(dp_aux->dev); return ret; } diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 76f1395..2c5706a 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -309,6 +309,10 @@ static int dp_display_bind(struct device *dev, struct device *master, goto end; } + pm_runtime_enable(dev); devm_pm_runtime_enable() removes need for a cleanup. + pm_runtime_set_autosuspend_delay(dev, 1000); + pm_runtime_use_autosuspend(dev); Why do you want to use autosuspend here? + return 0; end: return rc; @@ -320,9 +324,8 @@ static void dp_display_unbind(struct device *dev, struct device *master, struct dp_display_private *dp = dev_get_dp_display_private(dev); struct msm_drm_private *priv = dev_get_drvdata(master); - /* disable all HPD interrupts */ - if (dp->core_initialized) - dp_catalog_hpd_config_intr(dp->catalog, DP_DP_HPD_INT_MASK, false); + pm_runtime_dont_use_autosuspend(dev); + pm_runtime_disable(dev); kthread_stop(dp->ev_tsk); @@ -466,10 +469,12 @@ static void dp_display_host_init(struct dp_display_private *dp) dp->dp_display.connector_type, dp->core_initialized, dp->phy_initialized); - dp_power_init(dp->power); - dp_ctrl_reset_irq_ctrl(dp->ctrl, true); - dp_aux_init(dp->aux); - dp->core_initialized = true; + if (!dp->core_initialized) { + dp_power_init(dp->power); + dp_ctrl_reset_irq_ctrl(dp->ctrl, true); + dp_aux_init(dp->aux); + dp->core_initialized = true; + } Is this relevant to PM runtime? I don't think so. } static void dp_display_host_deinit(struct dp_display_private *dp) @@ -478,10 +483,12 @@ static void dp_display_host_deinit(struct dp_display_private *dp) dp->dp_display.connector_type, dp->core_initialized, dp->phy_initialized); - dp_ctrl_reset_irq_ctrl(dp->ctrl, false); - dp_aux_deinit(dp->aux); - dp_power_deinit(dp->power); - dp->core_initialized = false; + if (dp->core_initialized) { + dp_ctrl_reset_irq_ctrl(dp->ctrl, false); + dp_aux_deinit(dp->aux); + dp_power_deinit(dp->power); + dp->core_initialized = false; + } } static int dp_display_usbpd_configure_cb(struct device *dev) @@ -1304,6 +1311,39 @@ static int dp_display_remove(struct platform_device *pdev) dp_display_deinit_sub_modules(dp); platform_set_drvdata(pdev, NULL); + pm_runtime_put_sync_suspend(>dev); + + return 0; +} + +static int dp_pm_runtime_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct msm_dp *dp_display = platform_get_drvdata(pdev); + struct dp_display_private *dp; + + dp = container_of(dp_display, struct dp_display_private, dp_display); + + dp_display_host_phy_exit(dp); + dp_catalog_ctrl_hpd_enable(dp->catalog); What? NO! + dp_display_host_deinit(dp); + + return 0; +} + +static int dp_pm_runtime_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct msm_dp *dp_display = platform_get_drvdata(pdev); + struct dp_display_private *dp; + + dp = container_of(dp_display, struct dp_display_private, dp_display); + + dp_display_host_init(dp); + if (dp_display->is_edp) { +
Re: [PATCH 09/12] drm/msm/adreno: Add adreno family
On 08/07/2023 02:52, Rob Clark wrote: On Thu, Jul 6, 2023 at 8:16 PM Dmitry Baryshkov wrote: On 07/07/2023 02:35, Konrad Dybcio wrote: On 6.07.2023 23:10, Rob Clark wrote: From: Rob Clark Sometimes it is useful to know the sub-generation (or "family"). And in any case, this helps us get away from infering the generation from the numerical chip-id. Signed-off-by: Rob Clark --- [...] .rev = ADRENO_REV(5, 0, 8, ANY_ID), +.family = ADRENO_5XX, .revn = 508, 508 is from 530 fam .fw = { [ADRENO_FW_PM4] = "a530_pm4.fw", @@ -156,6 +168,7 @@ static const struct adreno_info gpulist[] = { .zapfw = "a508_zap.mdt", }, { .rev = ADRENO_REV(5, 0, 9, ANY_ID), +.family = ADRENO_5XX, .revn = 509, 509 and 512 are from 540 fam .fw = { [ADRENO_FW_PM4] = "a530_pm4.fw", @@ -173,6 +186,7 @@ static const struct adreno_info gpulist[] = { .zapfw = "a512_zap.mdt", }, { .rev = ADRENO_REV(5, 1, 0, ANY_ID), +.family = ADRENO_5XX, .revn = 510, 510 is 530ish but I think it's closer to 505 or whatever the 8953 gpu was called I'd say, there were following generations here: - a505 / a506 / a508 - a509 / a512 - a510 - a530 - a540 Indeed a50x were close to a530 in some aspects and a509/512 being closer to a540, but I don't think they were the same family. As a practical matter, I chose to defer splitting a3xx/a4xx/a5xx into sub-generations, simply because we didn't have any use for that yet. For a2xx and a6xx there was a clear immediate use for (most of) it, and what isn't used falls out of usage of sub-generation classification we have in mesa, so I have a lot of confidence in the split. We can try and map it all out for the other gens now.. or simply just wait until there is a use for it. I'm not super against mapping it out better now, but didn't feel that there was any down side to just punting on that. It would be easy enough to do follow-up patches that refactor the code and split out the subgen enums at the same time. Sure. I think this can be coupled with split of the gpulist. BR, -R [...] -priv->is_a2xx = config.rev.core == 2; +priv->is_a2xx = info->family < ADRENO_3XX; is this variable even needed now that there are explicit family values? Konrad priv->has_cached_coherent = !!(info->quirks & ADRENO_QUIRK_HAS_CACHED_COHERENT); diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index 2e62a7ce9f13..75ff7fb46099 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -1079,8 +1079,13 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, u32 speedbin; int ret; +adreno_gpu->funcs = funcs; +adreno_gpu->info = adreno_info(config->rev); +adreno_gpu->rev = *rev; + /* Only handle the core clock when GMU is not in use (or is absent). */ -if (adreno_has_gmu_wrapper(adreno_gpu) || config->rev.core < 6) { +if (adreno_has_gmu_wrapper(adreno_gpu) || +adreno_gpu->info->family < ADRENO_6XX_GEN1) { /* * This can only be done before devm_pm_opp_of_add_table(), or * dev_pm_opp_set_config() will WARN_ON() @@ -1096,10 +1101,6 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, devm_pm_opp_set_clkname(dev, "core"); } -adreno_gpu->funcs = funcs; -adreno_gpu->info = adreno_info(config->rev); -adreno_gpu->rev = *rev; - if (adreno_read_speedbin(dev, ) || !speedbin) speedbin = 0x; adreno_gpu->speedbin = (uint16_t) (0x & speedbin); diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h index 6066cfaaea52..2fa14dcd4e40 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h @@ -29,6 +29,25 @@ enum { ADRENO_FW_MAX, }; +/** + * @enum adreno_family: identify generation and possibly sub-generation + * + * In some cases there are distinct sub-generations within a major revision + * so it helps to be able to group the GPU devices by generation and if + * necessary sub-generation. + */ +enum adreno_family { +ADRENO_2XX_GEN1, /* a20x */ +ADRENO_2XX_GEN2, /* a22x */ +ADRENO_3XX, +ADRENO_4XX, +ADRENO_5XX, +ADRENO_6XX_GEN1, /* a630 family */ +ADRENO_6XX_GEN2, /* a640 family */ +ADRENO_6XX_GEN3, /* a650 family */ +ADRENO_6XX_GEN4, /* a660 family */ +}; + #define ADRENO_QUIRK_TWO_PASS_USE_WFI BIT(0) #define ADRENO_QUIRK_FAULT_DETECT_MASK BIT(1) #define ADRENO_QUIRK_LMLOADKILL_DISABLEBIT(2) @@ -63,6 +82,7 @@ extern const struct adreno_reglist a660_hwcg[], a690_hwcg[]; struct adreno_info {
[PATCH v1 5/5] drm/msm/dp: move of_dp_aux_populate_bus() to probe for eDP
Move of_dp_aux_populate_bus() to dp_display_probe() for eDP from dp_display_bind() so that probe deferral cases can be handled effectively Signed-off-by: Kuogee Hsieh --- drivers/gpu/drm/msm/dp/dp_aux.c | 25 drivers/gpu/drm/msm/dp/dp_display.c | 79 +++-- 2 files changed, 65 insertions(+), 39 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_aux.c b/drivers/gpu/drm/msm/dp/dp_aux.c index c592064..c1baffb 100644 --- a/drivers/gpu/drm/msm/dp/dp_aux.c +++ b/drivers/gpu/drm/msm/dp/dp_aux.c @@ -505,6 +505,21 @@ void dp_aux_unregister(struct drm_dp_aux *dp_aux) drm_dp_aux_unregister(dp_aux); } +static int dp_wait_hpd_asserted(struct drm_dp_aux *dp_aux, +unsigned long wait_us) +{ + int ret; + struct dp_aux_private *aux; + + aux = container_of(dp_aux, struct dp_aux_private, dp_aux); + + pm_runtime_get_sync(aux->dev); + ret = dp_catalog_aux_wait_for_hpd_connect_state(aux->catalog); + pm_runtime_put_sync(aux->dev); + + return ret; +} + struct drm_dp_aux *dp_aux_get(struct device *dev, struct dp_catalog *catalog, bool is_edp) { @@ -528,6 +543,16 @@ struct drm_dp_aux *dp_aux_get(struct device *dev, struct dp_catalog *catalog, aux->catalog = catalog; aux->retry_cnt = 0; + /* +* Use the drm_dp_aux_init() to use the aux adapter +* before registering aux with the DRM device. +*/ + aux->dp_aux.name = "dpu_dp_aux"; + aux->dp_aux.dev = dev; + aux->dp_aux.transfer = dp_aux_transfer; + aux->dp_aux.wait_hpd_asserted = dp_wait_hpd_asserted; + drm_dp_aux_init(>dp_aux); + return >dp_aux; } diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 185f1eb..7ed4bea 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -302,10 +302,6 @@ static int dp_display_bind(struct device *dev, struct device *master, goto end; } - pm_runtime_enable(dev); - pm_runtime_set_autosuspend_delay(dev, 1000); - pm_runtime_use_autosuspend(dev); - return 0; end: return rc; @@ -322,8 +318,6 @@ static void dp_display_unbind(struct device *dev, struct device *master, kthread_stop(dp->ev_tsk); - of_dp_aux_depopulate_bus(dp->aux); - dp_power_client_deinit(dp->power); dp_unregister_audio_driver(dev, dp->audio); dp_aux_unregister(dp->aux); @@ -1245,6 +1239,29 @@ static const struct msm_dp_desc *dp_display_get_desc(struct platform_device *pde return NULL; } +static void of_dp_aux_depopulate_bus_void(void *data) +{ + of_dp_aux_depopulate_bus(data); +} + +static int dp_display_auxbus_emulation(struct dp_display_private *dp) +{ + struct device *dev = >pdev->dev; + struct device_node *aux_bus; + int ret = 0; + + aux_bus = of_get_child_by_name(dev->of_node, "aux-bus"); + + if (aux_bus) { + ret = devm_of_dp_aux_populate_bus(dp->aux, NULL); + + devm_add_action_or_reset(dev, of_dp_aux_depopulate_bus_void, +dp->aux); + } + + return ret; +} + static int dp_display_probe(struct platform_device *pdev) { int rc = 0; @@ -1290,8 +1307,18 @@ static int dp_display_probe(struct platform_device *pdev) platform_set_drvdata(pdev, >dp_display); + pm_runtime_enable(>dev); + pm_runtime_set_autosuspend_delay(>dev, 1000); + pm_runtime_use_autosuspend(>dev); + dp_display_request_irq(dp); + if (dp->dp_display.is_edp) { + rc = dp_display_auxbus_emulation(dp); + if (rc) + DRM_ERROR("eDP aux-bus emulation failed, rc=%d\n", rc); + } + rc = component_add(>dev, _display_comp_ops); if (rc) { DRM_ERROR("component add failed, rc=%d\n", rc); @@ -1306,11 +1333,14 @@ static int dp_display_remove(struct platform_device *pdev) struct dp_display_private *dp = dev_get_dp_display_private(>dev); component_del(>dev, _display_comp_ops); - dp_display_deinit_sub_modules(dp); - platform_set_drvdata(pdev, NULL); + + pm_runtime_dont_use_autosuspend(>dev); + pm_runtime_disable(>dev); pm_runtime_put_sync_suspend(>dev); + dp_display_deinit_sub_modules(dp); + return 0; } @@ -1514,31 +1544,10 @@ void msm_dp_debugfs_init(struct msm_dp *dp_display, struct drm_minor *minor) static int dp_display_get_next_bridge(struct msm_dp *dp) { - int rc; + int rc = 0; struct dp_display_private *dp_priv; - struct device_node *aux_bus; - struct device *dev; dp_priv = container_of(dp, struct dp_display_private, dp_display); - dev = _priv->pdev->dev; - aux_bus = of_get_child_by_name(dev->of_node, "aux-bus"); -
[PATCH v1 4/5] drm/msm/dp: move relevant dp initialization code from bind() to probe()
In preparation of moving edp of_dp_aux_populate_bus() to dp_display_probe(), move dp_display_request_irq(), dp->parser->parse() and dp_power_client_init() to dp_display_probe() too. Signed-off-by: Kuogee Hsieh --- drivers/gpu/drm/msm/dp/dp_display.c | 48 + drivers/gpu/drm/msm/dp/dp_display.h | 1 - 2 files changed, 22 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 44580c2..185f1eb 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -290,12 +290,6 @@ static int dp_display_bind(struct device *dev, struct device *master, goto end; } - rc = dp_power_client_init(dp->power); - if (rc) { - DRM_ERROR("Power client create failed\n"); - goto end; - } - rc = dp_register_audio_driver(dev, dp->audio); if (rc) { DRM_ERROR("Audio registration Dp failed\n"); @@ -752,6 +746,12 @@ static int dp_init_sub_modules(struct dp_display_private *dp) goto error; } + rc = dp->parser->parse(dp->parser); + if (rc) { + DRM_ERROR("device tree parsing failed\n"); + goto error; + } + dp->catalog = dp_catalog_get(dev, >parser->io); if (IS_ERR(dp->catalog)) { rc = PTR_ERR(dp->catalog); @@ -768,6 +768,12 @@ static int dp_init_sub_modules(struct dp_display_private *dp) goto error; } + rc = dp_power_client_init(dp->power); + if (rc) { + DRM_ERROR("Power client create failed\n"); + goto error; + } + dp->aux = dp_aux_get(dev, dp->catalog, dp->dp_display.is_edp); if (IS_ERR(dp->aux)) { rc = PTR_ERR(dp->aux); @@ -1196,26 +1202,20 @@ static irqreturn_t dp_display_irq_handler(int irq, void *dev_id) return ret; } -int dp_display_request_irq(struct msm_dp *dp_display) +static int dp_display_request_irq(struct dp_display_private *dp) { int rc = 0; - struct dp_display_private *dp; - - if (!dp_display) { - DRM_ERROR("invalid input\n"); - return -EINVAL; - } - - dp = container_of(dp_display, struct dp_display_private, dp_display); + struct device *dev = >pdev->dev; - dp->irq = irq_of_parse_and_map(dp->pdev->dev.of_node, 0); if (!dp->irq) { - DRM_ERROR("failed to get irq\n"); - return -EINVAL; + dp->irq = irq_of_parse_and_map(dp->pdev->dev.of_node, 0); + if (!dp->irq) { + DRM_ERROR("failed to get irq\n"); + return -EINVAL; + } } - rc = devm_request_irq(dp_display->drm_dev->dev, dp->irq, - dp_display_irq_handler, + rc = devm_request_irq(dev, dp->irq, dp_display_irq_handler, IRQF_TRIGGER_HIGH, "dp_display_isr", dp); if (rc < 0) { DRM_ERROR("failed to request IRQ%u: %d\n", @@ -1290,6 +1290,8 @@ static int dp_display_probe(struct platform_device *pdev) platform_set_drvdata(pdev, >dp_display); + dp_display_request_irq(dp); + rc = component_add(>dev, _display_comp_ops); if (rc) { DRM_ERROR("component add failed, rc=%d\n", rc); @@ -1574,12 +1576,6 @@ int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev, dp_priv = container_of(dp_display, struct dp_display_private, dp_display); - ret = dp_display_request_irq(dp_display); - if (ret) { - DRM_ERROR("request_irq failed, ret=%d\n", ret); - return ret; - } - ret = dp_display_get_next_bridge(dp_display); if (ret) return ret; diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h index 1e9415a..b3c08de 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.h +++ b/drivers/gpu/drm/msm/dp/dp_display.h @@ -35,7 +35,6 @@ struct msm_dp { int dp_display_set_plugged_cb(struct msm_dp *dp_display, hdmi_codec_plugged_cb fn, struct device *codec_dev); int dp_display_get_modes(struct msm_dp *dp_display); -int dp_display_request_irq(struct msm_dp *dp_display); bool dp_display_check_video_test(struct msm_dp *dp_display); int dp_display_get_test_bpp(struct msm_dp *dp_display); void dp_display_signal_audio_start(struct msm_dp *dp_display); -- 2.7.4
[PATCH v1 3/5] drm/msm/dp: delete EV_HPD_INIT_SETUP
EV_HPD_INIT_SETUP flag is used to trigger the initialization of external DP host controller. Since external DP host controller initialization had been incorporated into pm_runtime_resume(), this flag become obsolete. Lets get rid of it. Signed-off-by: Kuogee Hsieh --- drivers/gpu/drm/msm/dp/dp_display.c | 12 1 file changed, 12 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 2c5706a..44580c2 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -55,7 +55,6 @@ enum { enum { EV_NO_EVENT, /* hpd events */ - EV_HPD_INIT_SETUP, EV_HPD_PLUG_INT, EV_IRQ_HPD_INT, EV_HPD_UNPLUG_INT, @@ -1119,9 +1118,6 @@ static int hpd_event_thread(void *data) spin_unlock_irqrestore(_priv->event_lock, flag); switch (todo->event_id) { - case EV_HPD_INIT_SETUP: - dp_display_host_init(dp_priv); - break; case EV_HPD_PLUG_INT: dp_hpd_plug_handle(dp_priv, todo->data); break; @@ -1483,15 +1479,7 @@ void __exit msm_dp_unregister(void) void msm_dp_irq_postinstall(struct msm_dp *dp_display) { - struct dp_display_private *dp; - - if (!dp_display) - return; - - dp = container_of(dp_display, struct dp_display_private, dp_display); - if (!dp_display->is_edp) - dp_add_event(dp, EV_HPD_INIT_SETUP, 0, 0); } bool msm_dp_wide_bus_available(const struct msm_dp *dp_display) -- 2.7.4
[PATCH v1 2/5] drm/msm/dp: incorporate pm_runtime framework into DP driver
Incorporating pm runtime framework into DP driver so that power and clock resource handling can be centralized allowing easier control of these resources in preparation of registering aux bus uring probe. Signed-off-by: Kuogee Hsieh --- drivers/gpu/drm/msm/dp/dp_aux.c | 3 ++ drivers/gpu/drm/msm/dp/dp_display.c | 75 + 2 files changed, 63 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_aux.c b/drivers/gpu/drm/msm/dp/dp_aux.c index 8e3b677..c592064 100644 --- a/drivers/gpu/drm/msm/dp/dp_aux.c +++ b/drivers/gpu/drm/msm/dp/dp_aux.c @@ -291,6 +291,7 @@ static ssize_t dp_aux_transfer(struct drm_dp_aux *dp_aux, return -EINVAL; } + pm_runtime_get_sync(dp_aux->dev); mutex_lock(>mutex); if (!aux->initted) { ret = -EIO; @@ -364,6 +365,8 @@ static ssize_t dp_aux_transfer(struct drm_dp_aux *dp_aux, exit: mutex_unlock(>mutex); + pm_runtime_mark_last_busy(dp_aux->dev); + pm_runtime_put_autosuspend(dp_aux->dev); return ret; } diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 76f1395..2c5706a 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -309,6 +309,10 @@ static int dp_display_bind(struct device *dev, struct device *master, goto end; } + pm_runtime_enable(dev); + pm_runtime_set_autosuspend_delay(dev, 1000); + pm_runtime_use_autosuspend(dev); + return 0; end: return rc; @@ -320,9 +324,8 @@ static void dp_display_unbind(struct device *dev, struct device *master, struct dp_display_private *dp = dev_get_dp_display_private(dev); struct msm_drm_private *priv = dev_get_drvdata(master); - /* disable all HPD interrupts */ - if (dp->core_initialized) - dp_catalog_hpd_config_intr(dp->catalog, DP_DP_HPD_INT_MASK, false); + pm_runtime_dont_use_autosuspend(dev); + pm_runtime_disable(dev); kthread_stop(dp->ev_tsk); @@ -466,10 +469,12 @@ static void dp_display_host_init(struct dp_display_private *dp) dp->dp_display.connector_type, dp->core_initialized, dp->phy_initialized); - dp_power_init(dp->power); - dp_ctrl_reset_irq_ctrl(dp->ctrl, true); - dp_aux_init(dp->aux); - dp->core_initialized = true; + if (!dp->core_initialized) { + dp_power_init(dp->power); + dp_ctrl_reset_irq_ctrl(dp->ctrl, true); + dp_aux_init(dp->aux); + dp->core_initialized = true; + } } static void dp_display_host_deinit(struct dp_display_private *dp) @@ -478,10 +483,12 @@ static void dp_display_host_deinit(struct dp_display_private *dp) dp->dp_display.connector_type, dp->core_initialized, dp->phy_initialized); - dp_ctrl_reset_irq_ctrl(dp->ctrl, false); - dp_aux_deinit(dp->aux); - dp_power_deinit(dp->power); - dp->core_initialized = false; + if (dp->core_initialized) { + dp_ctrl_reset_irq_ctrl(dp->ctrl, false); + dp_aux_deinit(dp->aux); + dp_power_deinit(dp->power); + dp->core_initialized = false; + } } static int dp_display_usbpd_configure_cb(struct device *dev) @@ -1304,6 +1311,39 @@ static int dp_display_remove(struct platform_device *pdev) dp_display_deinit_sub_modules(dp); platform_set_drvdata(pdev, NULL); + pm_runtime_put_sync_suspend(>dev); + + return 0; +} + +static int dp_pm_runtime_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct msm_dp *dp_display = platform_get_drvdata(pdev); + struct dp_display_private *dp; + + dp = container_of(dp_display, struct dp_display_private, dp_display); + + dp_display_host_phy_exit(dp); + dp_catalog_ctrl_hpd_enable(dp->catalog); + dp_display_host_deinit(dp); + + return 0; +} + +static int dp_pm_runtime_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct msm_dp *dp_display = platform_get_drvdata(pdev); + struct dp_display_private *dp; + + dp = container_of(dp_display, struct dp_display_private, dp_display); + + dp_display_host_init(dp); + if (dp_display->is_edp) { + dp_catalog_ctrl_hpd_enable(dp->catalog); + dp_display_host_phy_init(dp); + } return 0; } @@ -1409,6 +1449,7 @@ static int dp_pm_suspend(struct device *dev) } static const struct dev_pm_ops dp_pm_ops = { + SET_RUNTIME_PM_OPS(dp_pm_runtime_suspend, dp_pm_runtime_resume, NULL) .suspend = dp_pm_suspend, .resume = dp_pm_resume, }; @@ -1493,10 +1534,6 @@ static int dp_display_get_next_bridge(struct msm_dp *dp) aux_bus =
[PATCH v1 1/5] drm/msm/dp: remove pm_runtime_xxx() from dp_power.c
Since both pm_runtime_resume() and pm_runtime_suspend() are not populated at dp_pm_ops. Those pm_runtime_get/put() functions within dp_power.c will not have any effects in addition to increase/decrease power counter. Also pm_runtime_xxx() should be executed at top layer. Signed-off-by: Kuogee Hsieh --- drivers/gpu/drm/msm/dp/dp_power.c | 9 - 1 file changed, 9 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_power.c b/drivers/gpu/drm/msm/dp/dp_power.c index 5cb84ca..ed2f62a 100644 --- a/drivers/gpu/drm/msm/dp/dp_power.c +++ b/drivers/gpu/drm/msm/dp/dp_power.c @@ -152,8 +152,6 @@ int dp_power_client_init(struct dp_power *dp_power) power = container_of(dp_power, struct dp_power_private, dp_power); - pm_runtime_enable(power->dev); - return dp_power_clk_init(power); } @@ -162,8 +160,6 @@ void dp_power_client_deinit(struct dp_power *dp_power) struct dp_power_private *power; power = container_of(dp_power, struct dp_power_private, dp_power); - - pm_runtime_disable(power->dev); } int dp_power_init(struct dp_power *dp_power) @@ -173,11 +169,7 @@ int dp_power_init(struct dp_power *dp_power) power = container_of(dp_power, struct dp_power_private, dp_power); - pm_runtime_get_sync(power->dev); - rc = dp_power_clk_enable(dp_power, DP_CORE_PM, true); - if (rc) - pm_runtime_put_sync(power->dev); return rc; } @@ -189,7 +181,6 @@ int dp_power_deinit(struct dp_power *dp_power) power = container_of(dp_power, struct dp_power_private, dp_power); dp_power_clk_enable(dp_power, DP_CORE_PM, false); - pm_runtime_put_sync(power->dev); return 0; } -- 2.7.4
Re: [PATCH 09/12] drm/msm/adreno: Add adreno family
On Thu, Jul 6, 2023 at 8:16 PM Dmitry Baryshkov wrote: > > On 07/07/2023 02:35, Konrad Dybcio wrote: > > On 6.07.2023 23:10, Rob Clark wrote: > >> From: Rob Clark > >> > >> Sometimes it is useful to know the sub-generation (or "family"). And in > >> any case, this helps us get away from infering the generation from the > >> numerical chip-id. > >> > >> Signed-off-by: Rob Clark > >> --- > > [...] > > > >> .rev = ADRENO_REV(5, 0, 8, ANY_ID), > >> +.family = ADRENO_5XX, > >> .revn = 508, > > 508 is from 530 fam > > > >> .fw = { > >> [ADRENO_FW_PM4] = "a530_pm4.fw", > >> @@ -156,6 +168,7 @@ static const struct adreno_info gpulist[] = { > >> .zapfw = "a508_zap.mdt", > >> }, { > >> .rev = ADRENO_REV(5, 0, 9, ANY_ID), > >> +.family = ADRENO_5XX, > >> .revn = 509, > > 509 and 512 are from 540 fam > > > >> .fw = { > >> [ADRENO_FW_PM4] = "a530_pm4.fw", > >> @@ -173,6 +186,7 @@ static const struct adreno_info gpulist[] = { > >> .zapfw = "a512_zap.mdt", > >> }, { > >> .rev = ADRENO_REV(5, 1, 0, ANY_ID), > >> +.family = ADRENO_5XX, > >> .revn = 510, > > 510 is 530ish but I think it's closer to 505 or whatever the > > 8953 gpu was called > > I'd say, there were following generations here: > > - a505 / a506 / a508 > - a509 / a512 > - a510 > - a530 > - a540 > > Indeed a50x were close to a530 in some aspects and a509/512 being closer > to a540, but I don't think they were the same family. As a practical matter, I chose to defer splitting a3xx/a4xx/a5xx into sub-generations, simply because we didn't have any use for that yet. For a2xx and a6xx there was a clear immediate use for (most of) it, and what isn't used falls out of usage of sub-generation classification we have in mesa, so I have a lot of confidence in the split. We can try and map it all out for the other gens now.. or simply just wait until there is a use for it. I'm not super against mapping it out better now, but didn't feel that there was any down side to just punting on that. It would be easy enough to do follow-up patches that refactor the code and split out the subgen enums at the same time. BR, -R > > > > [...] > > > >> -priv->is_a2xx = config.rev.core == 2; > >> +priv->is_a2xx = info->family < ADRENO_3XX; > > is this variable even needed now that there are explicit family values? > > > > Konrad > >> priv->has_cached_coherent = > >> !!(info->quirks & ADRENO_QUIRK_HAS_CACHED_COHERENT); > >> > >> diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c > >> b/drivers/gpu/drm/msm/adreno/adreno_gpu.c > >> index 2e62a7ce9f13..75ff7fb46099 100644 > >> --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c > >> +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c > >> @@ -1079,8 +1079,13 @@ int adreno_gpu_init(struct drm_device *drm, struct > >> platform_device *pdev, > >> u32 speedbin; > >> int ret; > >> > >> +adreno_gpu->funcs = funcs; > >> +adreno_gpu->info = adreno_info(config->rev); > >> +adreno_gpu->rev = *rev; > >> + > >> /* Only handle the core clock when GMU is not in use (or is absent). > >> */ > >> -if (adreno_has_gmu_wrapper(adreno_gpu) || config->rev.core < 6) { > >> +if (adreno_has_gmu_wrapper(adreno_gpu) || > >> +adreno_gpu->info->family < ADRENO_6XX_GEN1) { > >> /* > >> * This can only be done before devm_pm_opp_of_add_table(), or > >> * dev_pm_opp_set_config() will WARN_ON() > >> @@ -1096,10 +1101,6 @@ int adreno_gpu_init(struct drm_device *drm, struct > >> platform_device *pdev, > >> devm_pm_opp_set_clkname(dev, "core"); > >> } > >> > >> -adreno_gpu->funcs = funcs; > >> -adreno_gpu->info = adreno_info(config->rev); > >> -adreno_gpu->rev = *rev; > >> - > >> if (adreno_read_speedbin(dev, ) || !speedbin) > >> speedbin = 0x; > >> adreno_gpu->speedbin = (uint16_t) (0x & speedbin); > >> diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h > >> b/drivers/gpu/drm/msm/adreno/adreno_gpu.h > >> index 6066cfaaea52..2fa14dcd4e40 100644 > >> --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h > >> +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h > >> @@ -29,6 +29,25 @@ enum { > >> ADRENO_FW_MAX, > >> }; > >> > >> +/** > >> + * @enum adreno_family: identify generation and possibly sub-generation > >> + * > >> + * In some cases there are distinct sub-generations within a major > >> revision > >> + * so it helps to be able to group the GPU devices by generation and if > >> + * necessary sub-generation. > >> + */ > >> +enum adreno_family { > >> +ADRENO_2XX_GEN1, /* a20x */ > >> +ADRENO_2XX_GEN2, /* a22x */ > >> +ADRENO_3XX, > >> +ADRENO_4XX, > >> +ADRENO_5XX, > >> +ADRENO_6XX_GEN1, /* a630 family */ > >> +ADRENO_6XX_GEN2, /* a640 family */
[PATCH v1 0/5] incorporate pm runtime framework and eDP clean up
Incorporate pm runtime framework into DP driver and clean up eDP by moving of_dp_aux_populate_bus() to probe() Kuogee Hsieh (5): drm/msm/dp: remove pm_runtime_xxx() from dp_power.c drm/msm/dp: incorporate pm_runtime framework into DP driver drm/msm/dp: delete EV_HPD_INIT_SETUP drm/msm/dp: move relevant dp initialization code from bind() to probe() drm/msm/dp: move of_dp_aux_populate_bus() to probe for eDP drivers/gpu/drm/msm/dp/dp_aux.c | 28 + drivers/gpu/drm/msm/dp/dp_display.c | 204 +--- drivers/gpu/drm/msm/dp/dp_display.h | 1 - drivers/gpu/drm/msm/dp/dp_power.c | 9 -- 4 files changed, 145 insertions(+), 97 deletions(-) -- 2.7.4
Re: [PATCH 01/13] drm/msm/dpu: cleanup dpu_kms_hw_init error path
On 08/07/2023 02:25, Konrad Dybcio wrote: On 7.07.2023 22:37, Dmitry Baryshkov wrote: It was noticed that dpu_kms_hw_init()'s error path contains several labels which point to the same code path. Replace all of them with a single label. Suggested-by: Konrad Dybcio it's the first time I'm seeing this code It is Suggested-by, not something else. And you pointed it out in https://lore.kernel.org/linux-arm-msm/6d598438-f10f-8678-7878-829b8b3ae...@linaro.org/ Konrad Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 21 + 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index c11b3ab572ab..e7ac02e92f42 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -1037,7 +1037,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms) if (!dpu_kms->catalog) { DPU_ERROR("device config not known!\n"); rc = -EINVAL; - goto power_error; + goto err_pm_put; } /* @@ -1047,13 +1047,13 @@ static int dpu_kms_hw_init(struct msm_kms *kms) rc = _dpu_kms_mmu_init(dpu_kms); if (rc) { DPU_ERROR("dpu_kms_mmu_init failed: %d\n", rc); - goto power_error; + goto err_pm_put; } rc = dpu_rm_init(_kms->rm, dpu_kms->catalog, dpu_kms->mmio); if (rc) { DPU_ERROR("rm init failed: %d\n", rc); - goto power_error; + goto err_pm_put; } dpu_kms->rm_init = true; @@ -1065,7 +1065,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms) rc = PTR_ERR(dpu_kms->hw_mdp); DPU_ERROR("failed to get hw_mdp: %d\n", rc); dpu_kms->hw_mdp = NULL; - goto power_error; + goto err_pm_put; } for (i = 0; i < dpu_kms->catalog->vbif_count; i++) { @@ -1076,7 +1076,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms) if (IS_ERR(hw)) { rc = PTR_ERR(hw); DPU_ERROR("failed to init vbif %d: %d\n", vbif->id, rc); - goto power_error; + goto err_pm_put; } dpu_kms->hw_vbif[vbif->id] = hw; @@ -1092,7 +1092,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms) rc = dpu_core_perf_init(_kms->perf, dpu_kms->catalog->perf, max_core_clk_rate); if (rc) { DPU_ERROR("failed to init perf %d\n", rc); - goto perf_err; + goto err_pm_put; } dpu_kms->hw_intr = dpu_hw_intr_init(dpu_kms->mmio, dpu_kms->catalog); @@ -1100,7 +1100,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms) rc = PTR_ERR(dpu_kms->hw_intr); DPU_ERROR("hw_intr init failed: %d\n", rc); dpu_kms->hw_intr = NULL; - goto hw_intr_init_err; + goto err_pm_put; } dev->mode_config.min_width = 0; @@ -1125,7 +1125,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms) rc = _dpu_kms_drm_obj_init(dpu_kms); if (rc) { DPU_ERROR("modeset init failed: %d\n", rc); - goto drm_obj_init_err; + goto err_pm_put; } dpu_vbif_init_memtypes(dpu_kms); @@ -1134,10 +1134,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms) return 0; -drm_obj_init_err: -hw_intr_init_err: -perf_err: -power_error: +err_pm_put: pm_runtime_put_sync(_kms->pdev->dev); error: _dpu_kms_hw_destroy(dpu_kms); -- With best wishes Dmitry
Re: [PATCH 01/13] drm/msm/dpu: cleanup dpu_kms_hw_init error path
On 7.07.2023 22:37, Dmitry Baryshkov wrote: > It was noticed that dpu_kms_hw_init()'s error path contains several > labels which point to the same code path. Replace all of them with a > single label. > > Suggested-by: Konrad Dybcio it's the first time I'm seeing this code Konrad > Signed-off-by: Dmitry Baryshkov > --- > drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 21 + > 1 file changed, 9 insertions(+), 12 deletions(-) > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c > b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c > index c11b3ab572ab..e7ac02e92f42 100644 > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c > @@ -1037,7 +1037,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms) > if (!dpu_kms->catalog) { > DPU_ERROR("device config not known!\n"); > rc = -EINVAL; > - goto power_error; > + goto err_pm_put; > } > > /* > @@ -1047,13 +1047,13 @@ static int dpu_kms_hw_init(struct msm_kms *kms) > rc = _dpu_kms_mmu_init(dpu_kms); > if (rc) { > DPU_ERROR("dpu_kms_mmu_init failed: %d\n", rc); > - goto power_error; > + goto err_pm_put; > } > > rc = dpu_rm_init(_kms->rm, dpu_kms->catalog, dpu_kms->mmio); > if (rc) { > DPU_ERROR("rm init failed: %d\n", rc); > - goto power_error; > + goto err_pm_put; > } > > dpu_kms->rm_init = true; > @@ -1065,7 +1065,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms) > rc = PTR_ERR(dpu_kms->hw_mdp); > DPU_ERROR("failed to get hw_mdp: %d\n", rc); > dpu_kms->hw_mdp = NULL; > - goto power_error; > + goto err_pm_put; > } > > for (i = 0; i < dpu_kms->catalog->vbif_count; i++) { > @@ -1076,7 +1076,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms) > if (IS_ERR(hw)) { > rc = PTR_ERR(hw); > DPU_ERROR("failed to init vbif %d: %d\n", vbif->id, rc); > - goto power_error; > + goto err_pm_put; > } > > dpu_kms->hw_vbif[vbif->id] = hw; > @@ -1092,7 +1092,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms) > rc = dpu_core_perf_init(_kms->perf, dpu_kms->catalog->perf, > max_core_clk_rate); > if (rc) { > DPU_ERROR("failed to init perf %d\n", rc); > - goto perf_err; > + goto err_pm_put; > } > > dpu_kms->hw_intr = dpu_hw_intr_init(dpu_kms->mmio, dpu_kms->catalog); > @@ -1100,7 +1100,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms) > rc = PTR_ERR(dpu_kms->hw_intr); > DPU_ERROR("hw_intr init failed: %d\n", rc); > dpu_kms->hw_intr = NULL; > - goto hw_intr_init_err; > + goto err_pm_put; > } > > dev->mode_config.min_width = 0; > @@ -1125,7 +1125,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms) > rc = _dpu_kms_drm_obj_init(dpu_kms); > if (rc) { > DPU_ERROR("modeset init failed: %d\n", rc); > - goto drm_obj_init_err; > + goto err_pm_put; > } > > dpu_vbif_init_memtypes(dpu_kms); > @@ -1134,10 +1134,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms) > > return 0; > > -drm_obj_init_err: > -hw_intr_init_err: > -perf_err: > -power_error: > +err_pm_put: > pm_runtime_put_sync(_kms->pdev->dev); > error: > _dpu_kms_hw_destroy(dpu_kms);
[PATCH v2 06/13] drm/msm/dpu: use devres-managed allocation for HW blocks
Use devm_kzalloc to create HW block structure. This allows us to remove corresponding kfree and drop all dpu_hw_*_destroy() functions as well as dpu_rm_destroy(), which becomes empty afterwards. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c| 19 ++-- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h| 16 ++-- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c| 12 ++- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h| 10 ++- .../gpu/drm/msm/disp/dpu1/dpu_hw_dsc_1_2.c| 7 +- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c | 16 ++-- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h | 12 +-- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c | 15 ++-- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h | 12 +-- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c | 14 ++- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h | 12 +-- .../gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.c| 14 ++- .../gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.h| 13 +-- .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c | 14 ++- .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h | 13 +-- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c | 15 ++-- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h | 7 +- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c | 14 ++- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h | 12 +-- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 8 +- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 1 - drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c| 90 +++ drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h| 11 +-- 23 files changed, 119 insertions(+), 238 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c index c278fb9d2b5b..d22e3f11ae34 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c @@ -4,6 +4,9 @@ */ #include + +#include + #include "dpu_hwio.h" #include "dpu_hw_ctl.h" #include "dpu_kms.h" @@ -674,14 +677,15 @@ static void _setup_ctl_ops(struct dpu_hw_ctl_ops *ops, ops->set_active_pipes = dpu_hw_ctl_set_fetch_pipe_active; }; -struct dpu_hw_ctl *dpu_hw_ctl_init(const struct dpu_ctl_cfg *cfg, - void __iomem *addr, - u32 mixer_count, - const struct dpu_lm_cfg *mixer) +struct dpu_hw_ctl *dpu_hw_ctl_init(struct drm_device *dev, + const struct dpu_ctl_cfg *cfg, + void __iomem *addr, + u32 mixer_count, + const struct dpu_lm_cfg *mixer) { struct dpu_hw_ctl *c; - c = kzalloc(sizeof(*c), GFP_KERNEL); + c = drmm_kzalloc(dev, sizeof(*c), GFP_KERNEL); if (!c) return ERR_PTR(-ENOMEM); @@ -696,8 +700,3 @@ struct dpu_hw_ctl *dpu_hw_ctl_init(const struct dpu_ctl_cfg *cfg, return c; } - -void dpu_hw_ctl_destroy(struct dpu_hw_ctl *ctx) -{ - kfree(ctx); -} diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h index 1c242298ff2e..279ebd8dfbff 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h @@ -274,20 +274,16 @@ static inline struct dpu_hw_ctl *to_dpu_hw_ctl(struct dpu_hw_blk *hw) /** * dpu_hw_ctl_init() - Initializes the ctl_path hw driver object. * Should be called before accessing any ctl_path register. + * @dev: Corresponding device for devres management * @cfg: ctl_path catalog entry for which driver object is required * @addr: mapped register io address of MDP * @mixer_count: Number of mixers in @mixer * @mixer: Pointer to an array of Layer Mixers defined in the catalog */ -struct dpu_hw_ctl *dpu_hw_ctl_init(const struct dpu_ctl_cfg *cfg, - void __iomem *addr, - u32 mixer_count, - const struct dpu_lm_cfg *mixer); - -/** - * dpu_hw_ctl_destroy(): Destroys ctl driver context - * should be called to free the context - */ -void dpu_hw_ctl_destroy(struct dpu_hw_ctl *ctx); +struct dpu_hw_ctl *dpu_hw_ctl_init(struct drm_device *dev, + const struct dpu_ctl_cfg *cfg, + void __iomem *addr, + u32 mixer_count, + const struct dpu_lm_cfg *mixer); #endif /*_DPU_HW_CTL_H */ diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c index 509dbaa51d87..5e9aad1b2aa2 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c @@ -3,6 +3,8 @@ * Copyright (c) 2020-2022, Linaro Limited */ +#include + #include #include "dpu_kms.h" @@ -188,12 +190,13 @@ static void _setup_dsc_ops(struct dpu_hw_dsc_ops *ops, ops->dsc_bind_pingpong_blk = dpu_hw_dsc_bind_pingpong_blk; }; -struct dpu_hw_dsc *dpu_hw_dsc_init(const struct dpu_dsc_cfg *cfg, +struct
[PATCH v2 13/13] drm/msm/dpu: use drmm-managed allocation for dpu_encoder_virt
It is incorrect to use devm-managed memory allocations for DRM data structures exposed to userspace. They should use drmm_ allocations. Change struct dpu_encoder allocation to use drmm_encoder_alloc(). This removes the need to perform any actions on encoder destruction. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 50 + 1 file changed, 10 insertions(+), 40 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index b42176ce4a3a..65c6c863f7c6 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -443,23 +443,6 @@ int dpu_encoder_get_linecount(struct drm_encoder *drm_enc) return linecount; } -static void dpu_encoder_destroy(struct drm_encoder *drm_enc) -{ - struct dpu_encoder_virt *dpu_enc = NULL; - int i = 0; - - if (!drm_enc) { - DPU_ERROR("invalid encoder\n"); - return; - } - - dpu_enc = to_dpu_encoder_virt(drm_enc); - DPU_DEBUG_ENC(dpu_enc, "\n"); - - drm_encoder_cleanup(drm_enc); - mutex_destroy(_enc->enc_lock); -} - void dpu_encoder_helper_split_config( struct dpu_encoder_phys *phys_enc, enum dpu_intf interface) @@ -2365,7 +2348,6 @@ static const struct drm_encoder_helper_funcs dpu_encoder_helper_funcs = { }; static const struct drm_encoder_funcs dpu_encoder_funcs = { - .destroy = dpu_encoder_destroy, .late_register = dpu_encoder_late_register, .early_unregister = dpu_encoder_early_unregister, }; @@ -2376,20 +2358,13 @@ struct drm_encoder *dpu_encoder_init(struct drm_device *dev, { struct msm_drm_private *priv = dev->dev_private; struct dpu_kms *dpu_kms = to_dpu_kms(priv->kms); - struct drm_encoder *drm_enc = NULL; - struct dpu_encoder_virt *dpu_enc = NULL; - int ret = 0; + struct dpu_encoder_virt *dpu_enc; + int ret; - dpu_enc = devm_kzalloc(dev->dev, sizeof(*dpu_enc), GFP_KERNEL); - if (!dpu_enc) - return ERR_PTR(-ENOMEM); - - ret = drm_encoder_init(dev, _enc->base, _encoder_funcs, - drm_enc_mode, NULL); - if (ret) { - devm_kfree(dev->dev, dpu_enc); - return ERR_PTR(ret); - } + dpu_enc = drmm_encoder_alloc(dev, struct dpu_encoder_virt, base, +_encoder_funcs, drm_enc_mode, NULL); + if (IS_ERR(dpu_enc)) + return ERR_CAST(dpu_enc); drm_encoder_helper_add(_enc->base, _encoder_helper_funcs); @@ -2399,8 +2374,10 @@ struct drm_encoder *dpu_encoder_init(struct drm_device *dev, mutex_init(_enc->rc_lock); ret = dpu_encoder_setup_display(dpu_enc, dpu_kms, disp_info); - if (ret) - goto fail; + if (ret) { + DPU_ERROR("failed to setup encoder\n"); + return ERR_PTR(-ENOMEM); + } atomic_set(_enc->frame_done_timeout_ms, 0); timer_setup(_enc->frame_done_timer, @@ -2426,13 +2403,6 @@ struct drm_encoder *dpu_encoder_init(struct drm_device *dev, DPU_DEBUG_ENC(dpu_enc, "created\n"); return _enc->base; - -fail: - DPU_ERROR("failed to create encoder\n"); - if (drm_enc) - dpu_encoder_destroy(drm_enc); - - return ERR_PTR(ret); } int dpu_encoder_wait_for_event(struct drm_encoder *drm_enc, -- 2.39.2
[PATCH v2 04/13] drm/msm/dpu: use devres-managed allocation for VBIF data
Use devm_kzalloc to create VBIF data structure. This allows us to remove corresponding kfree and drop dpu_hw_intr_destroy() function. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.c | 14 ++ drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h | 8 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 11 +++ 3 files changed, 13 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.c index a5121a50b2bb..98e34afde2d2 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.c @@ -2,6 +2,8 @@ /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. */ +#include + #include "dpu_hwio.h" #include "dpu_hw_catalog.h" #include "dpu_hw_vbif.h" @@ -211,12 +213,13 @@ static void _setup_vbif_ops(struct dpu_hw_vbif_ops *ops, ops->set_write_gather_en = dpu_hw_set_write_gather_en; } -struct dpu_hw_vbif *dpu_hw_vbif_init(const struct dpu_vbif_cfg *cfg, - void __iomem *addr) +struct dpu_hw_vbif *dpu_hw_vbif_init(struct drm_device *dev, +const struct dpu_vbif_cfg *cfg, +void __iomem *addr) { struct dpu_hw_vbif *c; - c = kzalloc(sizeof(*c), GFP_KERNEL); + c = drmm_kzalloc(dev, sizeof(*c), GFP_KERNEL); if (!c) return ERR_PTR(-ENOMEM); @@ -234,8 +237,3 @@ struct dpu_hw_vbif *dpu_hw_vbif_init(const struct dpu_vbif_cfg *cfg, return c; } - -void dpu_hw_vbif_destroy(struct dpu_hw_vbif *vbif) -{ - kfree(vbif); -} diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h index 7e10d2a172b4..e2b4307500e4 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h @@ -108,12 +108,12 @@ struct dpu_hw_vbif { /** * dpu_hw_vbif_init() - Initializes the VBIF driver for the passed * VBIF catalog entry. + * @dev: Corresponding device for devres management * @cfg: VBIF catalog entry for which driver object is required * @addr: Mapped register io address of MDSS */ -struct dpu_hw_vbif *dpu_hw_vbif_init(const struct dpu_vbif_cfg *cfg, - void __iomem *addr); - -void dpu_hw_vbif_destroy(struct dpu_hw_vbif *vbif); +struct dpu_hw_vbif *dpu_hw_vbif_init(struct drm_device *dev, +const struct dpu_vbif_cfg *cfg, +void __iomem *addr); #endif /*_DPU_HW_VBIF_H */ diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index ef232dc838c7..f7723f89cbbc 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -812,13 +812,8 @@ static void _dpu_kms_hw_destroy(struct dpu_kms *dpu_kms) /* safe to call these more than once during shutdown */ _dpu_kms_mmu_destroy(dpu_kms); - if (dpu_kms->catalog) { - for (i = 0; i < ARRAY_SIZE(dpu_kms->hw_vbif); i++) { - if (dpu_kms->hw_vbif[i]) { - dpu_hw_vbif_destroy(dpu_kms->hw_vbif[i]); - dpu_kms->hw_vbif[i] = NULL; - } - } + for (i = 0; i < ARRAY_SIZE(dpu_kms->hw_vbif); i++) { + dpu_kms->hw_vbif[i] = NULL; } if (dpu_kms->rm_init) @@ -1070,7 +1065,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms) struct dpu_hw_vbif *hw; const struct dpu_vbif_cfg *vbif = _kms->catalog->vbif[i]; - hw = dpu_hw_vbif_init(vbif, dpu_kms->vbif[vbif->id]); + hw = dpu_hw_vbif_init(dev, vbif, dpu_kms->vbif[vbif->id]); if (IS_ERR(hw)) { rc = PTR_ERR(hw); DPU_ERROR("failed to init vbif %d: %d\n", vbif->id, rc); -- 2.39.2
[PATCH v2 08/13] drm/msm/dpu: remove QoS teardown on plane destruction
There is little point in disabling QoS on plane destruction: it happens during DPU device destruction process, after which there will be no running planes. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 7 --- 1 file changed, 7 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index aba5185e1d66..f114efee1b57 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -1173,17 +1173,10 @@ static void dpu_plane_atomic_update(struct drm_plane *plane, static void dpu_plane_destroy(struct drm_plane *plane) { struct dpu_plane *pdpu = plane ? to_dpu_plane(plane) : NULL; - struct dpu_plane_state *pstate; DPU_DEBUG_PLANE(pdpu, "\n"); if (pdpu) { - pstate = to_dpu_plane_state(plane->state); - _dpu_plane_set_qos_ctrl(plane, >pipe, false); - - if (pstate->r_pipe.sspp) - _dpu_plane_set_qos_ctrl(plane, >r_pipe, false); - /* this will destroy the states as well */ drm_plane_cleanup(plane); -- 2.39.2
[PATCH v2 10/13] drm/msm/dpu: use drmm-managed allocation for dpu_crtc
Change struct dpu_crtc allocation to use drmm_crtc_alloc_with_planes(). This removes the need to perform any actions on CRTC destruction. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 25 +++- 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c index 214229d11e3e..a1fcb690c687 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -51,17 +51,6 @@ static struct dpu_kms *_dpu_crtc_get_kms(struct drm_crtc *crtc) return to_dpu_kms(priv->kms); } -static void dpu_crtc_destroy(struct drm_crtc *crtc) -{ - struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc); - - if (!crtc) - return; - - drm_crtc_cleanup(crtc); - kfree(dpu_crtc); -} - static struct drm_encoder *get_encoder_from_crtc(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; @@ -1433,7 +1422,6 @@ static int dpu_crtc_late_register(struct drm_crtc *crtc) static const struct drm_crtc_funcs dpu_crtc_funcs = { .set_config = drm_atomic_helper_set_config, - .destroy = dpu_crtc_destroy, .page_flip = drm_atomic_helper_page_flip, .reset = dpu_crtc_reset, .atomic_duplicate_state = dpu_crtc_duplicate_state, @@ -1467,9 +1455,13 @@ struct drm_crtc *dpu_crtc_init(struct drm_device *dev, struct drm_plane *plane, struct dpu_crtc *dpu_crtc = NULL; int i, ret; - dpu_crtc = kzalloc(sizeof(*dpu_crtc), GFP_KERNEL); - if (!dpu_crtc) - return ERR_PTR(-ENOMEM); + dpu_crtc = drmm_crtc_alloc_with_planes(dev, struct dpu_crtc, base, + plane, cursor, + _crtc_funcs, + NULL); + + if (IS_ERR(dpu_crtc)) + return ERR_CAST(dpu_crtc); crtc = _crtc->base; crtc->dev = dev; @@ -1489,9 +1481,6 @@ struct drm_crtc *dpu_crtc_init(struct drm_device *dev, struct drm_plane *plane, dpu_crtc_frame_event_work); } - drm_crtc_init_with_planes(dev, crtc, plane, cursor, _crtc_funcs, - NULL); - drm_crtc_helper_add(crtc, _crtc_helper_funcs); if (dpu_kms->catalog->dspp_count) -- 2.39.2
[PATCH v2 12/13] drm/msm/dpu: drop dpu_encoder_phys_ops::destroy
Drop the dpu_encoder_phys_ops' destroy() callback. No phys backend implements it anymore, so it is useless. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c| 18 -- .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 2 -- 2 files changed, 20 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 7c2cd9ce8acd..b42176ce4a3a 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -456,24 +456,6 @@ static void dpu_encoder_destroy(struct drm_encoder *drm_enc) dpu_enc = to_dpu_encoder_virt(drm_enc); DPU_DEBUG_ENC(dpu_enc, "\n"); - mutex_lock(_enc->enc_lock); - - for (i = 0; i < dpu_enc->num_phys_encs; i++) { - struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i]; - - if (phys->ops.destroy) { - phys->ops.destroy(phys); - --dpu_enc->num_phys_encs; - dpu_enc->phys_encs[i] = NULL; - } - } - - if (dpu_enc->num_phys_encs) - DPU_ERROR_ENC(dpu_enc, "expected 0 num_phys_encs not %d\n", - dpu_enc->num_phys_encs); - dpu_enc->num_phys_encs = 0; - mutex_unlock(_enc->enc_lock); - drm_encoder_cleanup(drm_enc); mutex_destroy(_enc->enc_lock); } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h index 4fb0d95f3061..757ce58f958b 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h @@ -72,7 +72,6 @@ struct dpu_encoder_phys; * @enable:DRM Call. Enable a DRM mode. * @disable: DRM Call. Disable mode. * @atomic_check: DRM Call. Atomic check new DRM state. - * @destroy: DRM Call. Destroy and release resources. * @control_vblank_irq Register/Deregister for VBLANK IRQ * @wait_for_commit_done: Wait for hardware to have flushed the * current pending frames to hardware @@ -102,7 +101,6 @@ struct dpu_encoder_phys_ops { int (*atomic_check)(struct dpu_encoder_phys *encoder, struct drm_crtc_state *crtc_state, struct drm_connector_state *conn_state); - void (*destroy)(struct dpu_encoder_phys *encoder); int (*control_vblank_irq)(struct dpu_encoder_phys *enc, bool enable); int (*wait_for_commit_done)(struct dpu_encoder_phys *phys_enc); int (*wait_for_tx_complete)(struct dpu_encoder_phys *phys_enc); -- 2.39.2
[PATCH v2 11/13] drm/msm/dpu: use drmm-managed allocation for dpu_encoder_phys
Change struct allocation of encoder's phys backend data to use drmm_kzalloc(). This removes the need to perform any actions on encoder destruction. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 9 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 8 --- .../drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c | 15 - .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 13 .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 21 --- 5 files changed, 22 insertions(+), 44 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 493905a5b63a..7c2cd9ce8acd 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -2199,6 +2199,7 @@ static void dpu_encoder_early_unregister(struct drm_encoder *encoder) } static int dpu_encoder_virt_add_phys_encs( + struct drm_device *dev, struct msm_display_info *disp_info, struct dpu_encoder_virt *dpu_enc, struct dpu_enc_phys_init_params *params) @@ -2220,7 +2221,7 @@ static int dpu_encoder_virt_add_phys_encs( if (disp_info->intf_type == INTF_WB) { - enc = dpu_encoder_phys_wb_init(params); + enc = dpu_encoder_phys_wb_init(dev, params); if (IS_ERR(enc)) { DPU_ERROR_ENC(dpu_enc, "failed to init wb enc: %ld\n", @@ -2231,7 +2232,7 @@ static int dpu_encoder_virt_add_phys_encs( dpu_enc->phys_encs[dpu_enc->num_phys_encs] = enc; ++dpu_enc->num_phys_encs; } else if (disp_info->is_cmd_mode) { - enc = dpu_encoder_phys_cmd_init(params); + enc = dpu_encoder_phys_cmd_init(dev, params); if (IS_ERR(enc)) { DPU_ERROR_ENC(dpu_enc, "failed to init cmd enc: %ld\n", @@ -2242,7 +2243,7 @@ static int dpu_encoder_virt_add_phys_encs( dpu_enc->phys_encs[dpu_enc->num_phys_encs] = enc; ++dpu_enc->num_phys_encs; } else { - enc = dpu_encoder_phys_vid_init(params); + enc = dpu_encoder_phys_vid_init(dev, params); if (IS_ERR(enc)) { DPU_ERROR_ENC(dpu_enc, "failed to init vid enc: %ld\n", @@ -2333,7 +2334,7 @@ static int dpu_encoder_setup_display(struct dpu_encoder_virt *dpu_enc, break; } - ret = dpu_encoder_virt_add_phys_encs(disp_info, + ret = dpu_encoder_virt_add_phys_encs(dpu_kms->dev, disp_info, dpu_enc, _params); if (ret) { DPU_ERROR_ENC(dpu_enc, "failed to add phys encs\n"); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h index d48558ede488..4fb0d95f3061 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h @@ -281,22 +281,24 @@ struct dpu_encoder_wait_info { * @p: Pointer to init params structure * Return: Error code or newly allocated encoder */ -struct dpu_encoder_phys *dpu_encoder_phys_vid_init( +struct dpu_encoder_phys *dpu_encoder_phys_vid_init(struct drm_device *dev, struct dpu_enc_phys_init_params *p); /** * dpu_encoder_phys_cmd_init - Construct a new command mode physical encoder + * @dev: Corresponding device for devres management * @p: Pointer to init params structure * Return: Error code or newly allocated encoder */ -struct dpu_encoder_phys *dpu_encoder_phys_cmd_init( +struct dpu_encoder_phys *dpu_encoder_phys_cmd_init(struct drm_device *dev, struct dpu_enc_phys_init_params *p); /** * dpu_encoder_phys_wb_init - initialize writeback encoder + * @dev: Corresponding device for devres management * @init: Pointer to init info structure with initialization params */ -struct dpu_encoder_phys *dpu_encoder_phys_wb_init( +struct dpu_encoder_phys *dpu_encoder_phys_wb_init(struct drm_device *dev, struct dpu_enc_phys_init_params *p); /** diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c index b856c6286c85..2958b64e6e5e 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c @@ -13,6 +13,8 @@ #include "dpu_trace.h" #include "disp/msm_disp_snapshot.h" +#include + #define DPU_DEBUG_CMDENC(e, fmt, ...) DPU_DEBUG("enc%d intf%d " fmt, \ (e) && (e)->base.parent ? \ (e)->base.parent->base.id : -1, \ @@ -563,14 +565,6 @@ static void dpu_encoder_phys_cmd_disable(struct dpu_encoder_phys *phys_enc) phys_enc->enable_state = DPU_ENC_DISABLED; } -static void dpu_encoder_phys_cmd_destroy(struct dpu_encoder_phys *phys_enc) -{ -
[PATCH v2 09/13] drm/msm/dpu: use drmm-managed allocation for dpu_plane
Change struct dpu_plane allocation to use drmm_universal_plane_alloc(). This removes the need to perform any actions on plane destruction. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 46 +-- 1 file changed, 10 insertions(+), 36 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index f114efee1b57..9d9e1cbf0dd7 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -1170,20 +1170,6 @@ static void dpu_plane_atomic_update(struct drm_plane *plane, } } -static void dpu_plane_destroy(struct drm_plane *plane) -{ - struct dpu_plane *pdpu = plane ? to_dpu_plane(plane) : NULL; - - DPU_DEBUG_PLANE(pdpu, "\n"); - - if (pdpu) { - /* this will destroy the states as well */ - drm_plane_cleanup(plane); - - kfree(pdpu); - } -} - static void dpu_plane_destroy_state(struct drm_plane *plane, struct drm_plane_state *state) { @@ -1353,7 +1339,6 @@ static bool dpu_plane_format_mod_supported(struct drm_plane *plane, static const struct drm_plane_funcs dpu_plane_funcs = { .update_plane = drm_atomic_helper_update_plane, .disable_plane = drm_atomic_helper_disable_plane, - .destroy = dpu_plane_destroy, .reset = dpu_plane_reset, .atomic_duplicate_state = dpu_plane_duplicate_state, .atomic_destroy_state = dpu_plane_destroy_state, @@ -1381,35 +1366,28 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev, struct dpu_hw_sspp *pipe_hw; uint32_t num_formats; uint32_t supported_rotations; - int ret = -EINVAL; - - /* create and zero local structure */ - pdpu = kzalloc(sizeof(*pdpu), GFP_KERNEL); - if (!pdpu) { - DPU_ERROR("[%u]failed to allocate local plane struct\n", pipe); - ret = -ENOMEM; - return ERR_PTR(ret); - } - - /* cache local stuff for later */ - plane = >base; - pdpu->pipe = pipe; + int ret; /* initialize underlying h/w driver */ pipe_hw = dpu_rm_get_sspp(>rm, pipe); if (!pipe_hw || !pipe_hw->cap || !pipe_hw->cap->sblk) { DPU_ERROR("[%u]SSPP is invalid\n", pipe); - goto clean_plane; + return ERR_PTR(-EINVAL); } format_list = pipe_hw->cap->sblk->format_list; num_formats = pipe_hw->cap->sblk->num_formats; - ret = drm_universal_plane_init(dev, plane, 0xff, _plane_funcs, + pdpu = drmm_universal_plane_alloc(dev, struct dpu_plane, base, + 0xff, _plane_funcs, format_list, num_formats, supported_format_modifiers, type, NULL); - if (ret) - goto clean_plane; + if (IS_ERR(pdpu)) + return ERR_CAST(pdpu); + + /* cache local stuff for later */ + plane = >base; + pdpu->pipe = pipe; pdpu->catalog = kms->catalog; @@ -1439,8 +1417,4 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev, DPU_DEBUG("%s created for pipe:%u id:%u\n", plane->name, pipe, plane->base.id); return plane; - -clean_plane: - kfree(pdpu); - return ERR_PTR(ret); } -- 2.39.2
[PATCH v2 07/13] drm/msm/dpu: drop unused dpu_plane::lock
The field dpu_plane::lock was never used for protecting any kind of data. Drop it now. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 6 -- 1 file changed, 6 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index c2aaaded07ed..aba5185e1d66 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -78,8 +78,6 @@ static const uint32_t qcom_compressed_supported_formats[] = { struct dpu_plane { struct drm_plane base; - struct mutex lock; - enum dpu_sspp pipe; uint32_t color_fill; @@ -1186,8 +1184,6 @@ static void dpu_plane_destroy(struct drm_plane *plane) if (pstate->r_pipe.sspp) _dpu_plane_set_qos_ctrl(plane, >r_pipe, false); - mutex_destroy(>lock); - /* this will destroy the states as well */ drm_plane_cleanup(plane); @@ -1447,8 +1443,6 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev, /* success! finalize initialization */ drm_plane_helper_add(plane, _plane_helper_funcs); - mutex_init(>lock); - DPU_DEBUG("%s created for pipe:%u id:%u\n", plane->name, pipe, plane->base.id); return plane; -- 2.39.2
[PATCH v2 05/13] drm/msm/dpu: use devres-managed allocation for MDP TOP
Use devm_kzalloc to create MDP TOP structure. This allows us to remove corresponding kfree and drop dpu_hw_mdp_destroy() function. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c | 17 +++-- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h | 8 +--- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c| 5 ++--- 3 files changed, 14 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c index cff48763ce25..481b373d9ccb 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c @@ -2,6 +2,8 @@ /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. */ +#include + #include "dpu_hwio.h" #include "dpu_hw_catalog.h" #include "dpu_hw_top.h" @@ -268,16 +270,17 @@ static void _setup_mdp_ops(struct dpu_hw_mdp_ops *ops, ops->intf_audio_select = dpu_hw_intf_audio_select; } -struct dpu_hw_mdp *dpu_hw_mdptop_init(const struct dpu_mdp_cfg *cfg, - void __iomem *addr, - const struct dpu_mdss_cfg *m) +struct dpu_hw_mdp *dpu_hw_mdptop_init(struct drm_device *dev, + const struct dpu_mdp_cfg *cfg, + void __iomem *addr, + const struct dpu_mdss_cfg *m) { struct dpu_hw_mdp *mdp; if (!addr) return ERR_PTR(-EINVAL); - mdp = kzalloc(sizeof(*mdp), GFP_KERNEL); + mdp = drmm_kzalloc(dev, sizeof(*mdp), GFP_KERNEL); if (!mdp) return ERR_PTR(-ENOMEM); @@ -292,9 +295,3 @@ struct dpu_hw_mdp *dpu_hw_mdptop_init(const struct dpu_mdp_cfg *cfg, return mdp; } - -void dpu_hw_mdp_destroy(struct dpu_hw_mdp *mdp) -{ - kfree(mdp); -} - diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h index 8b1463d2b2f0..6f3dc98087df 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h @@ -145,13 +145,15 @@ struct dpu_hw_mdp { /** * dpu_hw_mdptop_init - initializes the top driver for the passed config + * @dev: Corresponding device for devres management * @cfg: MDP TOP configuration from catalog * @addr: Mapped register io address of MDP * @m:Pointer to mdss catalog data */ -struct dpu_hw_mdp *dpu_hw_mdptop_init(const struct dpu_mdp_cfg *cfg, - void __iomem *addr, - const struct dpu_mdss_cfg *m); +struct dpu_hw_mdp *dpu_hw_mdptop_init(struct drm_device *dev, + const struct dpu_mdp_cfg *cfg, + void __iomem *addr, + const struct dpu_mdss_cfg *m); void dpu_hw_mdp_destroy(struct dpu_hw_mdp *mdp); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index f7723f89cbbc..48c3f8b6b88f 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -822,8 +822,6 @@ static void _dpu_kms_hw_destroy(struct dpu_kms *dpu_kms) dpu_kms->catalog = NULL; - if (dpu_kms->hw_mdp) - dpu_hw_mdp_destroy(dpu_kms->hw_mdp); dpu_kms->hw_mdp = NULL; } @@ -1051,7 +1049,8 @@ static int dpu_kms_hw_init(struct msm_kms *kms) dpu_kms->rm_init = true; - dpu_kms->hw_mdp = dpu_hw_mdptop_init(dpu_kms->catalog->mdp, + dpu_kms->hw_mdp = dpu_hw_mdptop_init(dev, +dpu_kms->catalog->mdp, dpu_kms->mmio, dpu_kms->catalog); if (IS_ERR(dpu_kms->hw_mdp)) { -- 2.39.2
[PATCH v2 03/13] drm/msm/dpu: use devres-managed allocation for interrupts data
Use devm_kzalloc to create interrupts data structure. This allows us to remove corresponding kfree and drop dpu_hw_intr_destroy() function. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c | 14 ++ drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h | 11 --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 4 +--- 3 files changed, 11 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c index 5e2d68ebb113..945f34736206 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c @@ -6,6 +6,8 @@ #include #include +#include + #include "dpu_core_irq.h" #include "dpu_kms.h" #include "dpu_hw_interrupts.h" @@ -441,8 +443,9 @@ static void __intr_offset(const struct dpu_mdss_cfg *m, hw->blk_addr = addr + m->mdp[0].base; } -struct dpu_hw_intr *dpu_hw_intr_init(void __iomem *addr, - const struct dpu_mdss_cfg *m) +struct dpu_hw_intr *dpu_hw_intr_init(struct drm_device *dev, +void __iomem *addr, +const struct dpu_mdss_cfg *m) { struct dpu_hw_intr *intr; int nirq = MDP_INTR_MAX * 32; @@ -450,7 +453,7 @@ struct dpu_hw_intr *dpu_hw_intr_init(void __iomem *addr, if (!addr || !m) return ERR_PTR(-EINVAL); - intr = kzalloc(struct_size(intr, irq_tbl, nirq), GFP_KERNEL); + intr = drmm_kzalloc(dev, struct_size(intr, irq_tbl, nirq), GFP_KERNEL); if (!intr) return ERR_PTR(-ENOMEM); @@ -465,11 +468,6 @@ struct dpu_hw_intr *dpu_hw_intr_init(void __iomem *addr, return intr; } -void dpu_hw_intr_destroy(struct dpu_hw_intr *intr) -{ - kfree(intr); -} - int dpu_core_irq_register_callback(struct dpu_kms *dpu_kms, int irq_idx, void (*irq_cb)(void *arg, int irq_idx), void *irq_arg) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h index 1f2dabc54c22..b0d7bb073203 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h @@ -70,15 +70,12 @@ struct dpu_hw_intr { /** * dpu_hw_intr_init(): Initializes the interrupts hw object + * @dev: Corresponding device for devres management * @addr: mapped register io address of MDP * @m:pointer to MDSS catalog data */ -struct dpu_hw_intr *dpu_hw_intr_init(void __iomem *addr, - const struct dpu_mdss_cfg *m); +struct dpu_hw_intr *dpu_hw_intr_init(struct drm_device *dev, +void __iomem *addr, +const struct dpu_mdss_cfg *m); -/** - * dpu_hw_intr_destroy(): Cleanup interrutps hw object - * @intr: pointer to interrupts hw object - */ -void dpu_hw_intr_destroy(struct dpu_hw_intr *intr); #endif diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index 85b8c9cc99ef..ef232dc838c7 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -807,8 +807,6 @@ static void _dpu_kms_hw_destroy(struct dpu_kms *dpu_kms) { int i; - if (dpu_kms->hw_intr) - dpu_hw_intr_destroy(dpu_kms->hw_intr); dpu_kms->hw_intr = NULL; /* safe to call these more than once during shutdown */ @@ -1095,7 +1093,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms) goto err_pm_put; } - dpu_kms->hw_intr = dpu_hw_intr_init(dpu_kms->mmio, dpu_kms->catalog); + dpu_kms->hw_intr = dpu_hw_intr_init(dev, dpu_kms->mmio, dpu_kms->catalog); if (IS_ERR(dpu_kms->hw_intr)) { rc = PTR_ERR(dpu_kms->hw_intr); DPU_ERROR("hw_intr init failed: %d\n", rc); -- 2.39.2
[PATCH v2 02/13] drm/msm/dpu: remove IS_ERR_OR_NULL for dpu_hw_intr_init() error handling
Using IS_ERR_OR_NULL() together with PTR_ERR() is a typical mistake. If the value is NULL, then the function will return 0 instead of a proper return code. Replace IS_ERR_OR_NULL() with IS_ERR() in the dpu_hw_intr_init() error check. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index e7ac02e92f42..85b8c9cc99ef 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -1096,7 +1096,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms) } dpu_kms->hw_intr = dpu_hw_intr_init(dpu_kms->mmio, dpu_kms->catalog); - if (IS_ERR_OR_NULL(dpu_kms->hw_intr)) { + if (IS_ERR(dpu_kms->hw_intr)) { rc = PTR_ERR(dpu_kms->hw_intr); DPU_ERROR("hw_intr init failed: %d\n", rc); dpu_kms->hw_intr = NULL; -- 2.39.2
[PATCH v2 01/13] drm/msm/dpu: cleanup dpu_kms_hw_init error path
It was noticed that dpu_kms_hw_init()'s error path contains several labels which point to the same code path. Replace all of them with a single label. Suggested-by: Konrad Dybcio Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 21 + 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index c11b3ab572ab..e7ac02e92f42 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -1037,7 +1037,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms) if (!dpu_kms->catalog) { DPU_ERROR("device config not known!\n"); rc = -EINVAL; - goto power_error; + goto err_pm_put; } /* @@ -1047,13 +1047,13 @@ static int dpu_kms_hw_init(struct msm_kms *kms) rc = _dpu_kms_mmu_init(dpu_kms); if (rc) { DPU_ERROR("dpu_kms_mmu_init failed: %d\n", rc); - goto power_error; + goto err_pm_put; } rc = dpu_rm_init(_kms->rm, dpu_kms->catalog, dpu_kms->mmio); if (rc) { DPU_ERROR("rm init failed: %d\n", rc); - goto power_error; + goto err_pm_put; } dpu_kms->rm_init = true; @@ -1065,7 +1065,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms) rc = PTR_ERR(dpu_kms->hw_mdp); DPU_ERROR("failed to get hw_mdp: %d\n", rc); dpu_kms->hw_mdp = NULL; - goto power_error; + goto err_pm_put; } for (i = 0; i < dpu_kms->catalog->vbif_count; i++) { @@ -1076,7 +1076,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms) if (IS_ERR(hw)) { rc = PTR_ERR(hw); DPU_ERROR("failed to init vbif %d: %d\n", vbif->id, rc); - goto power_error; + goto err_pm_put; } dpu_kms->hw_vbif[vbif->id] = hw; @@ -1092,7 +1092,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms) rc = dpu_core_perf_init(_kms->perf, dpu_kms->catalog->perf, max_core_clk_rate); if (rc) { DPU_ERROR("failed to init perf %d\n", rc); - goto perf_err; + goto err_pm_put; } dpu_kms->hw_intr = dpu_hw_intr_init(dpu_kms->mmio, dpu_kms->catalog); @@ -1100,7 +1100,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms) rc = PTR_ERR(dpu_kms->hw_intr); DPU_ERROR("hw_intr init failed: %d\n", rc); dpu_kms->hw_intr = NULL; - goto hw_intr_init_err; + goto err_pm_put; } dev->mode_config.min_width = 0; @@ -1125,7 +1125,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms) rc = _dpu_kms_drm_obj_init(dpu_kms); if (rc) { DPU_ERROR("modeset init failed: %d\n", rc); - goto drm_obj_init_err; + goto err_pm_put; } dpu_vbif_init_memtypes(dpu_kms); @@ -1134,10 +1134,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms) return 0; -drm_obj_init_err: -hw_intr_init_err: -perf_err: -power_error: +err_pm_put: pm_runtime_put_sync(_kms->pdev->dev); error: _dpu_kms_hw_destroy(dpu_kms); -- 2.39.2
[PATCH v2 00/13] drm/msm/dpu: use managed memory allocations
Please excuse me for sending v2 on the same day, it fixes erorr paths for drmm allocation code. In a lots of places in DPU driver memory is allocated by using the kzalloc and then manually freed using kfree. However thes memory chunks have a well-defined life cycle. They are either a part of the driver's runtime and can be devm_kzalloc'ed or are exposed to userspace via the DRM objects and thus can be drmm_alloc'ed. Implement corresponding runtime resource manangement for the DPU driver. Dependencies: [1]. [1] https://patchwork.freedesktop.org/series/118839/ Changes since v1: - Fix error handling for some of drmm_foo_alloc() functions, which return error pointer in case of an error rather than typical NULL. Dmitry Baryshkov (13): drm/msm/dpu: cleanup dpu_kms_hw_init error path drm/msm/dpu: remove IS_ERR_OR_NULL for dpu_hw_intr_init() error handling drm/msm/dpu: use devres-managed allocation for interrupts data drm/msm/dpu: use devres-managed allocation for VBIF data drm/msm/dpu: use devres-managed allocation for MDP TOP drm/msm/dpu: use devres-managed allocation for HW blocks drm/msm/dpu: drop unused dpu_plane::lock drm/msm/dpu: remove QoS teardown on plane destruction drm/msm/dpu: use drmm-managed allocation for dpu_plane drm/msm/dpu: use drmm-managed allocation for dpu_crtc drm/msm/dpu: use drmm-managed allocation for dpu_encoder_phys drm/msm/dpu: drop dpu_encoder_phys_ops::destroy drm/msm/dpu: use drmm-managed allocation for dpu_encoder_virt drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 25 ++ drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 77 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 10 +-- .../drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c | 15 +--- .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 13 +-- .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 21 + drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c| 19 ++-- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h| 16 ++-- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c| 12 ++- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h| 10 ++- .../gpu/drm/msm/disp/dpu1/dpu_hw_dsc_1_2.c| 7 +- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c | 16 ++-- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h | 12 +-- .../gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c | 14 ++- .../gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h | 11 +-- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c | 15 ++-- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h | 12 +-- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c | 14 ++- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h | 12 +-- .../gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.c| 14 ++- .../gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.h| 13 +-- .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c | 14 ++- .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h | 13 +-- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c | 15 ++-- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h | 7 +- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c| 17 ++-- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h| 8 +- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.c | 14 ++- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h | 8 +- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c | 14 ++- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h | 12 +-- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 51 --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 1 - drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 59 +++- drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c| 90 +++ drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h| 11 +-- 36 files changed, 216 insertions(+), 476 deletions(-) -- 2.39.2
[PATCH v5 6/6] drm/doc: Define KMS atomic state set
From: Pekka Paalanen Specify how the atomic state is maintained between userspace and kernel, plus the special case for async flips. Signed-off-by: Pekka Paalanen Signed-off-by: André Almeida --- v4: total rework by Pekka --- Documentation/gpu/drm-uapi.rst | 41 ++ 1 file changed, 41 insertions(+) diff --git a/Documentation/gpu/drm-uapi.rst b/Documentation/gpu/drm-uapi.rst index 65fb3036a580..6a1662c08901 100644 --- a/Documentation/gpu/drm-uapi.rst +++ b/Documentation/gpu/drm-uapi.rst @@ -486,3 +486,44 @@ and the CRTC index is its position in this array. .. kernel-doc:: include/uapi/drm/drm_mode.h :internal: + +KMS atomic state + + +An atomic commit can change multiple KMS properties in an atomic fashion, +without ever applying intermediate or partial state changes. Either the whole +commit succeeds or fails, and it will never be applied partially. This is the +fundamental improvement of the atomic API over the older non-atomic API which is +referred to as the "legacy API". Applying intermediate state could unexpectedly +fail, cause visible glitches, or delay reaching the final state. + +An atomic commit can be flagged with DRM_MODE_ATOMIC_TEST_ONLY, which means the +complete state change is validated but not applied. Userspace should use this +flag to validate any state change before asking to apply it. If validation fails +for any reason, userspace should attempt to fall back to another, perhaps +simpler, final state. This allows userspace to probe for various configurations +without causing visible glitches on screen and without the need to undo a +probing change. + +The changes recorded in an atomic commit apply on top the current KMS state in +the kernel. Hence, the complete new KMS state is the complete old KMS state with +the committed property settings done on top. The kernel will automatically avoid +no-operation changes, so it is safe and even expected for userspace to send +redundant property settings. No-operation changes do not count towards actually +needed changes, e.g. setting MODE_ID to a different blob with identical +contents as the current KMS state shall not be a modeset on its own. + +A "modeset" is a change in KMS state that might enable, disable, or temporarily +disrupt the emitted video signal, possibly causing visible glitches on screen. A +modeset may also take considerably more time to complete than other kinds of +changes, and the video sink might also need time to adapt to the new signal +properties. Therefore a modeset must be explicitly allowed with the flag +DRM_MODE_ATOMIC_ALLOW_MODESET. This in combination with +DRM_MODE_ATOMIC_TEST_ONLY allows userspace to determine if a state change is +likely to cause visible disruption on screen and avoid such changes when end +users do not expect them. + +An atomic commit with the flag DRM_MODE_PAGE_FLIP_ASYNC is allowed to +effectively change only the FB_ID property on any planes. No-operation changes +are ignored as always. Changing any other property will cause the commit to be +rejected. -- 2.41.0
[PATCH v5 5/6] drm: Refuse to async flip with atomic prop changes
Given that prop changes may lead to modesetting, which would defeat the fast path of the async flip, refuse any atomic prop change for async flips in atomic API. The only exceptions are the framebuffer ID to flip to and the mode ID, that could be referring to an identical mode. Signed-off-by: André Almeida --- v4: new patch --- drivers/gpu/drm/drm_atomic_helper.c | 5 +++ drivers/gpu/drm/drm_atomic_uapi.c | 52 +++-- drivers/gpu/drm/drm_crtc_internal.h | 2 +- drivers/gpu/drm/drm_mode_object.c | 2 +- 4 files changed, 56 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 2c2c9caf0be5..1e2973f0e1f6 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -629,6 +629,11 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, WARN_ON(!drm_modeset_is_locked(>mutex)); if (!drm_mode_equal(_crtc_state->mode, _crtc_state->mode)) { + if (new_crtc_state->async_flip) { + drm_dbg_atomic(dev, "[CRTC:%d:%s] no mode changes allowed during async flip\n", + crtc->base.id, crtc->name); + return -EINVAL; + } drm_dbg_atomic(dev, "[CRTC:%d:%s] mode changed\n", crtc->base.id, crtc->name); new_crtc_state->mode_changed = true; diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index dfd4cf7169df..536c21f53b5f 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -972,13 +972,28 @@ int drm_atomic_connector_commit_dpms(struct drm_atomic_state *state, return ret; } +static int drm_atomic_check_prop_changes(int ret, uint64_t old_val, uint64_t prop_value, +struct drm_property *prop) +{ + if (ret != 0 || old_val != prop_value) { + drm_dbg_atomic(prop->dev, + "[PROP:%d:%s] No prop can be changed during async flip\n", + prop->base.id, prop->name); + return -EINVAL; + } + + return 0; +} + int drm_atomic_set_property(struct drm_atomic_state *state, struct drm_file *file_priv, struct drm_mode_object *obj, struct drm_property *prop, - uint64_t prop_value) + uint64_t prop_value, + bool async_flip) { struct drm_mode_object *ref; + uint64_t old_val; int ret; if (!drm_property_change_valid_get(prop, prop_value, )) @@ -995,6 +1010,13 @@ int drm_atomic_set_property(struct drm_atomic_state *state, break; } + if (async_flip) { + ret = drm_atomic_connector_get_property(connector, connector_state, + prop, _val); + ret = drm_atomic_check_prop_changes(ret, old_val, prop_value, prop); + break; + } + ret = drm_atomic_connector_set_property(connector, connector_state, file_priv, prop, prop_value); @@ -1003,6 +1025,7 @@ int drm_atomic_set_property(struct drm_atomic_state *state, case DRM_MODE_OBJECT_CRTC: { struct drm_crtc *crtc = obj_to_crtc(obj); struct drm_crtc_state *crtc_state; + struct drm_mode_config *config = >dev->mode_config; crtc_state = drm_atomic_get_crtc_state(state, crtc); if (IS_ERR(crtc_state)) { @@ -1010,6 +1033,18 @@ int drm_atomic_set_property(struct drm_atomic_state *state, break; } + /* +* We allow mode_id changes here for async flips, because we +* check later on drm_atomic_helper_check_modeset() callers if +* there are modeset changes or they are equal +*/ + if (async_flip && prop != config->prop_mode_id) { + ret = drm_atomic_crtc_get_property(crtc, crtc_state, + prop, _val); + ret = drm_atomic_check_prop_changes(ret, old_val, prop_value, prop); + break; + } + ret = drm_atomic_crtc_set_property(crtc, crtc_state, prop, prop_value); break; @@ -1017,6 +1052,7 @@ int drm_atomic_set_property(struct drm_atomic_state *state, case DRM_MODE_OBJECT_PLANE: { struct drm_plane *plane =
[PATCH v5 4/6] amd/display: indicate support for atomic async page-flips on DC
From: Simon Ser amdgpu_dm_commit_planes() already sets the flip_immediate flag for async page-flips. This flag is used to set the UNP_FLIP_CONTROL register. Thus, no additional change is required to handle async page-flips with the atomic uAPI. Signed-off-by: Simon Ser Reviewed-by: André Almeida Reviewed-by: Alex Deucher Signed-off-by: André Almeida --- v4: no changes --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 1 - 1 file changed, 1 deletion(-) 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 258461826140..7acd73e5004f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3970,7 +3970,6 @@ static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev) adev_to_drm(adev)->mode_config.prefer_shadow = 1; /* indicates support for immediate flip */ adev_to_drm(adev)->mode_config.async_page_flip = true; - adev_to_drm(adev)->mode_config.atomic_async_page_flip_not_supported = true; state = kzalloc(sizeof(*state), GFP_KERNEL); if (!state) -- 2.41.0
[PATCH v5 3/6] drm: introduce drm_mode_config.atomic_async_page_flip_not_supported
From: Simon Ser This new field indicates whether the driver has the necessary logic to support async page-flips via the atomic uAPI. This is leveraged by the next commit to allow user-space to use this functionality. All atomic drivers setting drm_mode_config.async_page_flip are updated to also set drm_mode_config.atomic_async_page_flip_not_supported. We will gradually check and update these drivers to properly handle drm_crtc_state.async_flip in their atomic logic. The goal of this negative flag is the same as fb_modifiers_not_supported: we want to eventually get rid of all drivers missing atomic support for async flips. New drivers should not set this flag, instead they should support atomic async flips (if they support async flips at all). IOW, we don't want more drivers with async flip support for legacy but not atomic. Signed-off-by: Simon Ser Reviewed-by: André Almeida Reviewed-by: Alex Deucher Signed-off-by: André Almeida --- v4: no changes --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 1 + drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c | 1 + drivers/gpu/drm/i915/display/intel_display.c | 1 + drivers/gpu/drm/nouveau/nouveau_display.c | 1 + include/drm/drm_mode_config.h | 11 +++ 5 files changed, 15 insertions(+) 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 7acd73e5004f..258461826140 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3970,6 +3970,7 @@ static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev) adev_to_drm(adev)->mode_config.prefer_shadow = 1; /* indicates support for immediate flip */ adev_to_drm(adev)->mode_config.async_page_flip = true; + adev_to_drm(adev)->mode_config.atomic_async_page_flip_not_supported = true; state = kzalloc(sizeof(*state), GFP_KERNEL); if (!state) diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c index 29603561d501..8afb22b1e730 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c @@ -639,6 +639,7 @@ static int atmel_hlcdc_dc_modeset_init(struct drm_device *dev) dev->mode_config.max_height = dc->desc->max_height; dev->mode_config.funcs = _config_funcs; dev->mode_config.async_page_flip = true; + dev->mode_config.atomic_async_page_flip_not_supported = true; return 0; } diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 0aae9a1eb3d5..a5c503ca9168 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -8318,6 +8318,7 @@ static void intel_mode_config_init(struct drm_i915_private *i915) mode_config->helper_private = _mode_config_funcs; mode_config->async_page_flip = HAS_ASYNC_FLIPS(i915); + mode_config->atomic_async_page_flip_not_supported = true; /* * Maximum framebuffer dimensions, chosen to match diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index ec3487fc..f497dcd9e22f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -709,6 +709,7 @@ nouveau_display_create(struct drm_device *dev) dev->mode_config.async_page_flip = false; else dev->mode_config.async_page_flip = true; + dev->mode_config.atomic_async_page_flip_not_supported = true; drm_kms_helper_poll_init(dev); drm_kms_helper_poll_disable(dev); diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h index 973119a9176b..47b005671e6a 100644 --- a/include/drm/drm_mode_config.h +++ b/include/drm/drm_mode_config.h @@ -918,6 +918,17 @@ struct drm_mode_config { */ bool async_page_flip; + /** +* @atomic_async_page_flip_not_supported: +* +* If true, the driver does not support async page-flips with the +* atomic uAPI. This is only used by old drivers which haven't yet +* accomodated for _crtc_state.async_flip in their atomic logic, +* even if they have _mode_config.async_page_flip set to true. +* New drivers shall not set this flag. +*/ + bool atomic_async_page_flip_not_supported; + /** * @fb_modifiers_not_supported: * -- 2.41.0
[PATCH v5 2/6] drm: introduce DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP
From: Simon Ser This new kernel capability indicates whether async page-flips are supported via the atomic uAPI. DRM clients can use it to check for support before feeding DRM_MODE_PAGE_FLIP_ASYNC to the kernel. Make it clear that DRM_CAP_ASYNC_PAGE_FLIP is for legacy uAPI only. Signed-off-by: Simon Ser Reviewed-by: André Almeida Reviewed-by: Alex Deucher Signed-off-by: André Almeida --- v4: no changes --- drivers/gpu/drm/drm_ioctl.c | 5 + include/uapi/drm/drm.h | 10 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index 7c9d66ee917d..8f756b99260d 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -302,6 +302,11 @@ static int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_ case DRM_CAP_CRTC_IN_VBLANK_EVENT: req->value = 1; break; + case DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP: + req->value = drm_core_check_feature(dev, DRIVER_ATOMIC) && +dev->mode_config.async_page_flip && + !dev->mode_config.atomic_async_page_flip_not_supported; + break; default: return -EINVAL; } diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h index a87ca2d4..54c558f81f3c 100644 --- a/include/uapi/drm/drm.h +++ b/include/uapi/drm/drm.h @@ -706,7 +706,8 @@ struct drm_gem_open { /** * DRM_CAP_ASYNC_PAGE_FLIP * - * If set to 1, the driver supports _MODE_PAGE_FLIP_ASYNC. + * If set to 1, the driver supports _MODE_PAGE_FLIP_ASYNC for legacy + * page-flips. */ #define DRM_CAP_ASYNC_PAGE_FLIP0x7 /** @@ -767,6 +768,13 @@ struct drm_gem_open { * Documentation/gpu/drm-mm.rst, section "DRM Sync Objects". */ #define DRM_CAP_SYNCOBJ_TIMELINE 0x14 +/** + * DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP + * + * If set to 1, the driver supports _MODE_PAGE_FLIP_ASYNC for atomic + * commits. + */ +#define DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP 0x15 /* DRM_IOCTL_GET_CAP ioctl argument type */ struct drm_get_cap { -- 2.41.0
[PATCH v5 0/6] drm: Add support for atomic async page-flip
Hi, This work from me and Simon adds support for DRM_MODE_PAGE_FLIP_ASYNC through the atomic API. This feature is already available via the legacy API. The use case is to be able to present a new frame immediately (or as soon as possible), even if after missing a vblank. This might result in tearing, but it's useful when a high framerate is desired, such as for gaming. Differently from earlier versions, this one refuses to flip if any prop changes for async flips. The idea is that the fast path of immediate page flips doesn't play well with modeset changes, so only the fb_id can be changed. The exception is for mode_id changes, that might be referring to an identical mode (which would skip a modeset). This is done to make the async API more similar to the normal API. Thanks, André - User-space patch: https://github.com/Plagman/gamescope/pull/595 - IGT tests: https://gitlab.freedesktop.org/andrealmeid/igt-gpu-tools/-/tree/atomic_async_page_flip Changes from v4: - Documentation rewrote by Pekka Paalanen v4: https://lore.kernel.org/dri-devel/20230701020917.143394-1-andrealm...@igalia.com/ Changes from v3: - Add new patch to reject prop changes - Add a documentation clarifying the KMS atomic state set v3: https://lore.kernel.org/dri-devel/20220929184307.258331-1-cont...@emersion.fr/ André Almeida (1): drm: Refuse to async flip with atomic prop changes Pekka Paalanen (1): drm/doc: Define KMS atomic state set Simon Ser (4): drm: allow DRM_MODE_PAGE_FLIP_ASYNC for atomic commits drm: introduce DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP drm: introduce drm_mode_config.atomic_async_page_flip_not_supported amd/display: indicate support for atomic async page-flips on DC Documentation/gpu/drm-uapi.rst | 41 ++ drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c | 1 + drivers/gpu/drm/drm_atomic_helper.c | 5 ++ drivers/gpu/drm/drm_atomic_uapi.c| 80 ++-- drivers/gpu/drm/drm_crtc_internal.h | 2 +- drivers/gpu/drm/drm_ioctl.c | 5 ++ drivers/gpu/drm/drm_mode_object.c| 2 +- drivers/gpu/drm/i915/display/intel_display.c | 1 + drivers/gpu/drm/nouveau/nouveau_display.c| 1 + include/drm/drm_mode_config.h| 11 +++ include/uapi/drm/drm.h | 10 ++- include/uapi/drm/drm_mode.h | 9 +++ 12 files changed, 159 insertions(+), 9 deletions(-) -- 2.41.0
[PATCH v5 1/6] drm: allow DRM_MODE_PAGE_FLIP_ASYNC for atomic commits
From: Simon Ser If the driver supports it, allow user-space to supply the DRM_MODE_PAGE_FLIP_ASYNC flag to request an async page-flip. Set drm_crtc_state.async_flip accordingly. Document that drivers will reject atomic commits if an async flip isn't possible. This allows user-space to fall back to something else. For instance, Xorg falls back to a blit. Another option is to wait as close to the next vblank as possible before performing the page-flip to reduce latency. Signed-off-by: Simon Ser Reviewed-by: Alex Deucher Co-developed-by: André Almeida Signed-off-by: André Almeida --- v4: no changes --- drivers/gpu/drm/drm_atomic_uapi.c | 28 +--- include/uapi/drm/drm_mode.h | 9 + 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index d867e7f9f2cd..dfd4cf7169df 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -1286,6 +1286,18 @@ static void complete_signaling(struct drm_device *dev, kfree(fence_state); } +static void +set_async_flip(struct drm_atomic_state *state) +{ + struct drm_crtc *crtc; + struct drm_crtc_state *crtc_state; + int i; + + for_each_new_crtc_in_state(state, crtc, crtc_state, i) { + crtc_state->async_flip = true; + } +} + int drm_mode_atomic_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { @@ -1326,9 +1338,16 @@ int drm_mode_atomic_ioctl(struct drm_device *dev, } if (arg->flags & DRM_MODE_PAGE_FLIP_ASYNC) { - drm_dbg_atomic(dev, - "commit failed: invalid flag DRM_MODE_PAGE_FLIP_ASYNC\n"); - return -EINVAL; + if (!dev->mode_config.async_page_flip) { + drm_dbg_atomic(dev, + "commit failed: DRM_MODE_PAGE_FLIP_ASYNC not supported\n"); + return -EINVAL; + } + if (dev->mode_config.atomic_async_page_flip_not_supported) { + drm_dbg_atomic(dev, + "commit failed: DRM_MODE_PAGE_FLIP_ASYNC not supported with atomic\n"); + return -EINVAL; + } } /* can't test and expect an event at the same time. */ @@ -1426,6 +1445,9 @@ int drm_mode_atomic_ioctl(struct drm_device *dev, if (ret) goto out; + if (arg->flags & DRM_MODE_PAGE_FLIP_ASYNC) + set_async_flip(state); + if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) { ret = drm_atomic_check_only(state); } else if (arg->flags & DRM_MODE_ATOMIC_NONBLOCK) { diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index 46becedf5b2f..56342ba2c11a 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -949,6 +949,15 @@ struct hdr_output_metadata { * Request that the page-flip is performed as soon as possible, ie. with no * delay due to waiting for vblank. This may cause tearing to be visible on * the screen. + * + * When used with atomic uAPI, the driver will return an error if the hardware + * doesn't support performing an asynchronous page-flip for this update. + * User-space should handle this, e.g. by falling back to a regular page-flip. + * + * Note, some hardware might need to perform one last synchronous page-flip + * before being able to switch to asynchronous page-flips. As an exception, + * the driver will return success even though that first page-flip is not + * asynchronous. */ #define DRM_MODE_PAGE_FLIP_ASYNC 0x02 #define DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE 0x4 -- 2.41.0
[PATCH] drm/nouveau/nvkm/dp: Add hack to fix DP 1.3+ DPCD issues
Currently we use the drm_dp_dpcd_read_caps() helper in the DRM side of nouveau in order to read the DPCD of a DP connector, which makes sure we do the right thing and also check for extended DPCD caps. However, it turns out we're not currently doing this on the nvkm side since we don't have access to the drm_dp_aux structure there - which means that the DRM side of the driver and the NVKM side can end up with different DPCD capabilities for the same connector. Ideally to fix this, we want to start setting up the drm_dp_aux device in NVKM before we've made contact with the DRM side - which should be pretty easy to accomplish (I'm already working on it!). Until then however, let's workaround this problem by porting a copy of drm_dp_read_dpcd_caps() into NVKM - which should fix this issue. Issue: https://gitlab.freedesktop.org/drm/nouveau/-/issues/211 Signed-off-by: Lyude Paul --- drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c | 48 ++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c index 40c8ea43c42f..b8ac66b4a2c4 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c @@ -26,6 +26,8 @@ #include "head.h" #include "ior.h" +#include + #include #include #include @@ -634,6 +636,50 @@ nvkm_dp_enable_supported_link_rates(struct nvkm_outp *outp) return outp->dp.rates != 0; } +/* XXX: This is a big fat hack, and this is just drm_dp_read_dpcd_caps() + * converted to work inside nvkm. This is a temporary holdover until we start + * passing the drm_dp_aux device through NVKM + */ +static int +nvkm_dp_read_dpcd_caps(struct nvkm_outp *outp) +{ + struct nvkm_i2c_aux *aux = outp->dp.aux; + u8 dpcd_ext[DP_RECEIVER_CAP_SIZE]; + int ret; + + ret = nvkm_rdaux(aux, DPCD_RC00_DPCD_REV, outp->dp.dpcd, DP_RECEIVER_CAP_SIZE); + if (ret < 0) + return ret; + + /* +* Prior to DP1.3 the bit represented by +* DP_EXTENDED_RECEIVER_CAP_FIELD_PRESENT was reserved. +* If it is set DP_DPCD_REV at h could be at a value less than +* the true capability of the panel. The only way to check is to +* then compare h and 2200h. +*/ + if (!(outp->dp.dpcd[DP_TRAINING_AUX_RD_INTERVAL] & + DP_EXTENDED_RECEIVER_CAP_FIELD_PRESENT)) + return 0; + + ret = nvkm_rdaux(aux, DP_DP13_DPCD_REV, dpcd_ext, sizeof(dpcd_ext)); + if (ret < 0) + return ret; + + if (outp->dp.dpcd[DP_DPCD_REV] > dpcd_ext[DP_DPCD_REV]) { + OUTP_DBG(outp, "Extended DPCD rev less than base DPCD rev (%d > %d)\n", +outp->dp.dpcd[DP_DPCD_REV], dpcd_ext[DP_DPCD_REV]); + return 0; + } + + if (!memcmp(outp->dp.dpcd, dpcd_ext, sizeof(dpcd_ext))) + return 0; + + memcpy(outp->dp.dpcd, dpcd_ext, sizeof(dpcd_ext)); + + return 0; +} + void nvkm_dp_enable(struct nvkm_outp *outp, bool auxpwr) { @@ -689,7 +735,7 @@ nvkm_dp_enable(struct nvkm_outp *outp, bool auxpwr) memset(outp->dp.lttpr, 0x00, sizeof(outp->dp.lttpr)); } - if (!nvkm_rdaux(aux, DPCD_RC00_DPCD_REV, outp->dp.dpcd, sizeof(outp->dp.dpcd))) { + if (!nvkm_dp_read_dpcd_caps(outp)) { const u8 rates[] = { 0x1e, 0x14, 0x0a, 0x06, 0 }; const u8 *rate; int rate_max; -- 2.40.1
Re: [PATCH v4 6/6] drm/msm/dpu: Update dev core dump to dump registers of sub-blocks
On Fri, 7 Jul 2023 at 23:49, Ryan McCann wrote: > > My apologies for the private email, I hit reply instead of reply all by > accident. No problem, it happens sometimes. > > On 7/6/2023 5:24 PM, Dmitry Baryshkov wrote: > > On 06/07/2023 23:48, Ryan McCann wrote: > >> Currently, the device core dump mechanism does not dump registers of > >> sub-blocks within the DSPP, SSPP, DSC, and PINGPONG blocks. Edit > >> dpu_kms_mdp_snapshot function to account for sub-blocks. > >> > >> Signed-off-by: Ryan McCann > >> --- > >> drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 66 > >> ++--- > >> 1 file changed, 60 insertions(+), 6 deletions(-) > >> > >> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c > >> b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c > >> index 70dbb1204e6c..afc45d597d65 100644 > >> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c > >> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c > >> @@ -903,25 +903,58 @@ static void dpu_kms_mdp_snapshot(struct > >> msm_disp_state *disp_state, struct msm_k > >> cat->ctl[i].base, cat->ctl[i].name); > >> /* dump DSPP sub-blocks HW regs info */ > >> -for (i = 0; i < cat->dspp_count; i++) > >> +for (i = 0; i < cat->dspp_count; i++) { > >> msm_disp_snapshot_add_block(disp_state, cat->dspp[i].len, > >> dpu_kms->mmio + > >> cat->dspp[i].base, cat->dspp[i].name); > >> +if (cat->dspp[i].sblk && cat->dspp[i].sblk->pcc.len > 0) > >> +msm_disp_snapshot_add_block(disp_state, > >> cat->dspp[i].sblk->pcc.len, > >> +dpu_kms->mmio + cat->dspp[i].base + > >> +cat->dspp[i].sblk->pcc.base, "%s_%s", > > > > This might look simpler in the following form. Could you please consider > > it? > > > > > > void *base = dpu_kms + cat->dspp[i].base; > > > > msm_disp_snapshot_add_block(..., base, cat->dspp[i].name) > > > > if (!cat->dspp[i].sblk) > > continue; > > > > if (cat->dspp[i].sblk->pcc.len) > > msm_disp_snapshot_add_block(..., base + > > cat->dspp[i].sblk->pcc.base, ...); > > Regarding what we discussed in the private email, is what I had for base > in v2 > > (https://patchwork.freedesktop.org/patch/545690/?series=120249=1) > > essentially what you have in mind? > > > > >> +cat->dspp[i].name, > >> +cat->dspp[i].sblk->pcc.name); > >> +} > >> + > >> /* dump INTF sub-blocks HW regs info */ > >> for (i = 0; i < cat->intf_count; i++) > >> msm_disp_snapshot_add_block(disp_state, cat->intf[i].len, > >> dpu_kms->mmio + > >> cat->intf[i].base, cat->intf[i].name); > >> /* dump PP sub-blocks HW regs info */ > >> -for (i = 0; i < cat->pingpong_count; i++) > >> +for (i = 0; i < cat->pingpong_count; i++) { > >> msm_disp_snapshot_add_block(disp_state, > >> cat->pingpong[i].len, dpu_kms->mmio + > >> cat->pingpong[i].base, cat->pingpong[i].name); > >> +/* TE2 block has length of 0, so will not print it */ > >> + > >> +if (cat->pingpong[i].sblk && > >> cat->pingpong[i].sblk->dither.len > 0) > >> +msm_disp_snapshot_add_block(disp_state, > >> cat->pingpong[i].sblk->dither.len, > >> +dpu_kms->mmio + cat->pingpong[i].base + > >> +cat->pingpong[i].sblk->dither.base, "%s_%s", > >> +cat->pingpong[i].name, > >> +cat->pingpong[i].sblk->dither.name); > >> +} > >> + > >> /* dump SSPP sub-blocks HW regs info */ > >> -for (i = 0; i < cat->sspp_count; i++) > >> +for (i = 0; i < cat->sspp_count; i++) { > >> msm_disp_snapshot_add_block(disp_state, cat->sspp[i].len, > >> dpu_kms->mmio + > >> cat->sspp[i].base, cat->sspp[i].name); > >> +if (cat->sspp[i].sblk && cat->sspp[i].sblk->scaler_blk.len > 0) > >> +msm_disp_snapshot_add_block(disp_state, > >> cat->sspp[i].sblk->scaler_blk.len, > >> +dpu_kms->mmio + cat->sspp[i].base + > >> +cat->sspp[i].sblk->scaler_blk.base, "%s_%s", > >> +cat->sspp[i].name, > >> +cat->sspp[i].sblk->scaler_blk.name); > >> + > >> +if (cat->sspp[i].sblk && cat->sspp[i].sblk->csc_blk.len > 0) > >> +msm_disp_snapshot_add_block(disp_state, > >> cat->sspp[i].sblk->csc_blk.len, > >> +dpu_kms->mmio + cat->sspp[i].base + > >> +cat->sspp[i].sblk->csc_blk.base, "%s_%s", > >> +cat->sspp[i].name, > >> +cat->sspp[i].sblk->csc_blk.name); > >> +} > >> + > >> /* dump LM sub-blocks HW regs info */ > >> for (i = 0; i < cat->mixer_count; i++) > >> msm_disp_snapshot_add_block(disp_state, cat->mixer[i].len,
[PATCH v4] drm/virtio: conditionally allocate virtio_gpu_fence
We don't want to create a fence for every command submission. It's only necessary when userspace provides a waitable token for submission. This could be: 1) bo_handles, to be used with VIRTGPU_WAIT 2) out_fence_fd, to be used with dma_fence apis 3) a ring_idx provided with VIRTGPU_CONTEXT_PARAM_POLL_RINGS_MASK + DRM event API 4) syncobjs in the future The use case for just submitting a command to the host, and expecting no response. For example, gfxstream has GFXSTREAM_CONTEXT_PING that just wakes up the host side worker threads. There's also CROSS_DOMAIN_CMD_SEND which just sends data to the Wayland server. This prevents the need to signal the automatically created virtio_gpu_fence. In addition, VIRTGPU_EXECBUF_RING_IDX is checked when creating a DRM event object. VIRTGPU_CONTEXT_PARAM_POLL_RINGS_MASK is already defined in terms of per-context rings. It was theoretically possible to create a DRM event on the global timeline (ring_idx == 0), if the context enabled DRM event polling. However, that wouldn't work and userspace (Sommelier). Explicitly disallow it for clarity. Signed-off-by: Gurchetan Singh --- v2: Fix indent (Dmitry) v3: Refactor drm fence event checks to avoid possible NULL deref (Dmitry) v4: More detailed commit message about addition drm fence event checks (Dmitry) drivers/gpu/drm/virtio/virtgpu_submit.c | 28 + 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/virtio/virtgpu_submit.c b/drivers/gpu/drm/virtio/virtgpu_submit.c index cf3c04b16a7a..004364cf86d7 100644 --- a/drivers/gpu/drm/virtio/virtgpu_submit.c +++ b/drivers/gpu/drm/virtio/virtgpu_submit.c @@ -64,13 +64,9 @@ static int virtio_gpu_fence_event_create(struct drm_device *dev, struct virtio_gpu_fence *fence, u32 ring_idx) { - struct virtio_gpu_fpriv *vfpriv = file->driver_priv; struct virtio_gpu_fence_event *e = NULL; int ret; - if (!(vfpriv->ring_idx_mask & BIT_ULL(ring_idx))) - return 0; - e = kzalloc(sizeof(*e), GFP_KERNEL); if (!e) return -ENOMEM; @@ -161,21 +157,27 @@ static int virtio_gpu_init_submit(struct virtio_gpu_submit *submit, struct drm_file *file, u64 fence_ctx, u32 ring_idx) { + int err; + struct virtio_gpu_fence *out_fence; struct virtio_gpu_fpriv *vfpriv = file->driver_priv; struct virtio_gpu_device *vgdev = dev->dev_private; - struct virtio_gpu_fence *out_fence; - int err; + bool drm_fence_event = (exbuf->flags & VIRTGPU_EXECBUF_RING_IDX) && + (vfpriv->ring_idx_mask & BIT_ULL(ring_idx)); memset(submit, 0, sizeof(*submit)); - out_fence = virtio_gpu_fence_alloc(vgdev, fence_ctx, ring_idx); - if (!out_fence) - return -ENOMEM; + if ((exbuf->flags & VIRTGPU_EXECBUF_FENCE_FD_OUT) || drm_fence_event || +exbuf->num_bo_handles) + out_fence = virtio_gpu_fence_alloc(vgdev, fence_ctx, ring_idx); + else + out_fence = NULL; - err = virtio_gpu_fence_event_create(dev, file, out_fence, ring_idx); - if (err) { - dma_fence_put(_fence->f); - return err; + if (drm_fence_event) { + err = virtio_gpu_fence_event_create(dev, file, out_fence, ring_idx); + if (err) { + dma_fence_put(_fence->f); + return err; + } } submit->out_fence = out_fence; -- 2.41.0.255.g8b1d071c50-goog
Re: [PATCH] drm/nouveau/disp/g94: enable HDMI
Reviewed-by: Lyude Paul But seeing as I looked at this + some other patches yesterday I assume there's still more to this? On Fri, 2023-06-30 at 18:06 +0200, Karol Herbst wrote: > Cc: Ben Skeggs > Cc: Lyude Paul > Fixes: f530bc60a30b ("drm/nouveau/disp: move HDMI config into acquire + > infoframe methods") > Signed-off-by: Karol Herbst > --- > drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c | 1 + > 1 file changed, 1 insertion(+) > > diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c > b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c > index a4853c4e5ee3..67ef889a0c5f 100644 > --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c > +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c > @@ -295,6 +295,7 @@ g94_sor = { > .clock = nv50_sor_clock, > .war_2 = g94_sor_war_2, > .war_3 = g94_sor_war_3, > + .hdmi = _sor_hdmi, > .dp = _sor_dp, > }; > -- Cheers, Lyude Paul (she/her) Software Engineer at Red Hat
Re: [PATCH v4 2/8] drm/atomic: Add support for mouse hotspots
On 7/7/23 01:38, Pekka Paalanen wrote: That statement was based on the assumption that existing hypervisors and VM viewer applications are not prepared to deal with hotspots outside of cursor image. Therefore, if a guest is upgraded to a version that uses hotspots outside of cursor images, and the VM stack is not updated, it will malfunction. Therefore it is best to model the new UAPI in a way that is compatible with existing VM stack, especially since allowing this new feature (hotspots outside of cursor image) has no known benefits. Below I see my assumption was incorrect, but it still causes you to fall back to something less optimal. Okay, right. That's why I was saying that it's not a big deal either way to VMware, but I wanted to at least make the case for allowing somewhat arbitrary hotspots just because it is semantically meaningful, and I don't know if any other hypervisors care about allowing it more than we do. Essentially setting the hotspot properties means that the hypervisor console can choose to either draw the cursor where the plane is located, or use the cursor-plane + hotspot information to draw the cursor where the user's mouse is on the client. That works the same whether the hotspot is clamped or not. We mostly use clamping to avoid pathological cases (like a hotspot ot MAX_UINT32), and get away with it because real Guest applications that do this are very rare. My point here is that you can design the new Linux UAPI to help you: you can rule out cases that would lead to non-optimal behaviour, like falling back to the drawing of cursor plane you mention when it would be better to commandeer the cursor plane with the hotspot information. We can't though, because we can't trust the guest kernel any more than the kernel can trust userspace. So we need to handle these cases one way or another, both for older guests, and to ensure we don't have some security issue from a malicious guest kernel. The question of which input device corresponds to which cursor plane might be good to answer too. I presume the VM runner is configured to expose exactly one of each, so there can be only one association? As far as I know, all of the VM consoles are written as though they taking the place of what would the the physical monitors and input devices on a native machine. So they assume that there is one user, sitting in front of one console, and all monitors/input devices are being used by that user. Ok, but having a single user does not mean that there cannot be multiple independent pointers, especially on Wayland. The same with keyboards. True, and if the userspace is doing anything complicated here, the hypervisor has to be responsible for ensuring that whatever it's doing works with that, or else this system won't work. I don't know that the kernel is in a good position to police that. What do you mean by policing here? Isn't it the hypervisor that determines what virtual input devices will be available to the guest OS? Therefore, the hypervisor is in a position to expose exactly one pointer device and exactly one cursor plane to guest OS which means the guest OS cannot get the association wrong. If that's the general and expected hypervisor policy, then there is no need to design explicit device association in the guest kernel UAPI. If so, I'd like it to be mentioned in the kernel docs, too. I'm not entirely sure how to fit what you're calling a "pointer" into my mental model of what the hypervisor is doing... My definition: A pointer is a pointing input device that requires a cursor image to be drawn at the right location for it to be usable. Right, but normal desktops (and our consoles) expect multiple input devices to feed into a single cursor. So the connection between the on-screen cursor and the corresponding input-devices is not clear to me when you start talking about multiple pointers, even without any hypervisors in the picture. For a typical Linux Guest, we currently expose 3+ virtual mouse devices, and choose which one to send input to based on what their guest drivers are doing, and what kind of input we got from the client. We expect the input from all of those to end up in the same user desktop session, which we expect to own all the virtual screens, and that the user the only gets one cursor image from that. Why do you need to expose so many pointer devices? Just curious. For one, we don't know what drivers are actually going to be running in the Guest. If someone configured the Guest to not support the PS/2 mouse, or didn't have USB support compiled in, we still need to be able to send mouse input. (We actually ran into this for years with some Linux distro installers, where they had frozen their installer with some weird/older kernel configs and just didn't support our preferred vmmouse device.) So we plug them all in at boot, and then try to pick the one that looks the most active. But we also need to be able to
Re: [PATCH v4 6/6] drm/msm/dpu: Update dev core dump to dump registers of sub-blocks
My apologies for the private email, I hit reply instead of reply all by accident. On 7/6/2023 5:24 PM, Dmitry Baryshkov wrote: On 06/07/2023 23:48, Ryan McCann wrote: Currently, the device core dump mechanism does not dump registers of sub-blocks within the DSPP, SSPP, DSC, and PINGPONG blocks. Edit dpu_kms_mdp_snapshot function to account for sub-blocks. Signed-off-by: Ryan McCann --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 66 ++--- 1 file changed, 60 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index 70dbb1204e6c..afc45d597d65 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -903,25 +903,58 @@ static void dpu_kms_mdp_snapshot(struct msm_disp_state *disp_state, struct msm_k cat->ctl[i].base, cat->ctl[i].name); /* dump DSPP sub-blocks HW regs info */ - for (i = 0; i < cat->dspp_count; i++) + for (i = 0; i < cat->dspp_count; i++) { msm_disp_snapshot_add_block(disp_state, cat->dspp[i].len, dpu_kms->mmio + cat->dspp[i].base, cat->dspp[i].name); + if (cat->dspp[i].sblk && cat->dspp[i].sblk->pcc.len > 0) + msm_disp_snapshot_add_block(disp_state, cat->dspp[i].sblk->pcc.len, + dpu_kms->mmio + cat->dspp[i].base + + cat->dspp[i].sblk->pcc.base, "%s_%s", This might look simpler in the following form. Could you please consider it? void *base = dpu_kms + cat->dspp[i].base; msm_disp_snapshot_add_block(..., base, cat->dspp[i].name) if (!cat->dspp[i].sblk) continue; if (cat->dspp[i].sblk->pcc.len) msm_disp_snapshot_add_block(..., base + cat->dspp[i].sblk->pcc.base, ...); Regarding what we discussed in the private email, is what I had for base in v2 (https://patchwork.freedesktop.org/patch/545690/?series=120249=1) essentially what you have in mind? + cat->dspp[i].name, + cat->dspp[i].sblk->pcc.name); + } + /* dump INTF sub-blocks HW regs info */ for (i = 0; i < cat->intf_count; i++) msm_disp_snapshot_add_block(disp_state, cat->intf[i].len, dpu_kms->mmio + cat->intf[i].base, cat->intf[i].name); /* dump PP sub-blocks HW regs info */ - for (i = 0; i < cat->pingpong_count; i++) + for (i = 0; i < cat->pingpong_count; i++) { msm_disp_snapshot_add_block(disp_state, cat->pingpong[i].len, dpu_kms->mmio + cat->pingpong[i].base, cat->pingpong[i].name); + /* TE2 block has length of 0, so will not print it */ + + if (cat->pingpong[i].sblk && cat->pingpong[i].sblk->dither.len > 0) + msm_disp_snapshot_add_block(disp_state, cat->pingpong[i].sblk->dither.len, + dpu_kms->mmio + cat->pingpong[i].base + + cat->pingpong[i].sblk->dither.base, "%s_%s", + cat->pingpong[i].name, + cat->pingpong[i].sblk->dither.name); + } + /* dump SSPP sub-blocks HW regs info */ - for (i = 0; i < cat->sspp_count; i++) + for (i = 0; i < cat->sspp_count; i++) { msm_disp_snapshot_add_block(disp_state, cat->sspp[i].len, dpu_kms->mmio + cat->sspp[i].base, cat->sspp[i].name); + if (cat->sspp[i].sblk && cat->sspp[i].sblk->scaler_blk.len > 0) + msm_disp_snapshot_add_block(disp_state, cat->sspp[i].sblk->scaler_blk.len, + dpu_kms->mmio + cat->sspp[i].base + + cat->sspp[i].sblk->scaler_blk.base, "%s_%s", + cat->sspp[i].name, + cat->sspp[i].sblk->scaler_blk.name); + + if (cat->sspp[i].sblk && cat->sspp[i].sblk->csc_blk.len > 0) + msm_disp_snapshot_add_block(disp_state, cat->sspp[i].sblk->csc_blk.len, + dpu_kms->mmio + cat->sspp[i].base + + cat->sspp[i].sblk->csc_blk.base, "%s_%s", + cat->sspp[i].name, + cat->sspp[i].sblk->csc_blk.name); + } + /* dump LM sub-blocks HW regs info */ for (i = 0; i < cat->mixer_count; i++) msm_disp_snapshot_add_block(disp_state, cat->mixer[i].len, dpu_kms->mmio + @@ -943,9 +976,30 @@ static void dpu_kms_mdp_snapshot(struct msm_disp_state *disp_state, struct msm_k } /* dump DSC sub-blocks HW regs info */ - for (i = 0; i < cat->dsc_count; i++) - msm_disp_snapshot_add_block(disp_state, cat->dsc[i].len, dpu_kms->mmio + - cat->dsc[i].base, cat->dsc[i].name); + for (i = 0; i < cat->dsc_count; i++) { + if (cat->dsc[i].features & BIT(DPU_DSC_HW_REV_1_2)) { + struct dpu_dsc_blk enc = cat->dsc[i].sblk->enc; +
[PATCH 11/13] drm/msm/dpu: use drmm-managed allocation for dpu_encoder_phys
Change struct allocation of encoder's phys backend data to use drmm_kzalloc(). This removes the need to perform any actions on encoder destruction. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 9 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 8 --- .../drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c | 15 - .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 13 .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 21 --- 5 files changed, 22 insertions(+), 44 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 493905a5b63a..7c2cd9ce8acd 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -2199,6 +2199,7 @@ static void dpu_encoder_early_unregister(struct drm_encoder *encoder) } static int dpu_encoder_virt_add_phys_encs( + struct drm_device *dev, struct msm_display_info *disp_info, struct dpu_encoder_virt *dpu_enc, struct dpu_enc_phys_init_params *params) @@ -2220,7 +2221,7 @@ static int dpu_encoder_virt_add_phys_encs( if (disp_info->intf_type == INTF_WB) { - enc = dpu_encoder_phys_wb_init(params); + enc = dpu_encoder_phys_wb_init(dev, params); if (IS_ERR(enc)) { DPU_ERROR_ENC(dpu_enc, "failed to init wb enc: %ld\n", @@ -2231,7 +2232,7 @@ static int dpu_encoder_virt_add_phys_encs( dpu_enc->phys_encs[dpu_enc->num_phys_encs] = enc; ++dpu_enc->num_phys_encs; } else if (disp_info->is_cmd_mode) { - enc = dpu_encoder_phys_cmd_init(params); + enc = dpu_encoder_phys_cmd_init(dev, params); if (IS_ERR(enc)) { DPU_ERROR_ENC(dpu_enc, "failed to init cmd enc: %ld\n", @@ -2242,7 +2243,7 @@ static int dpu_encoder_virt_add_phys_encs( dpu_enc->phys_encs[dpu_enc->num_phys_encs] = enc; ++dpu_enc->num_phys_encs; } else { - enc = dpu_encoder_phys_vid_init(params); + enc = dpu_encoder_phys_vid_init(dev, params); if (IS_ERR(enc)) { DPU_ERROR_ENC(dpu_enc, "failed to init vid enc: %ld\n", @@ -2333,7 +2334,7 @@ static int dpu_encoder_setup_display(struct dpu_encoder_virt *dpu_enc, break; } - ret = dpu_encoder_virt_add_phys_encs(disp_info, + ret = dpu_encoder_virt_add_phys_encs(dpu_kms->dev, disp_info, dpu_enc, _params); if (ret) { DPU_ERROR_ENC(dpu_enc, "failed to add phys encs\n"); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h index d48558ede488..4fb0d95f3061 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h @@ -281,22 +281,24 @@ struct dpu_encoder_wait_info { * @p: Pointer to init params structure * Return: Error code or newly allocated encoder */ -struct dpu_encoder_phys *dpu_encoder_phys_vid_init( +struct dpu_encoder_phys *dpu_encoder_phys_vid_init(struct drm_device *dev, struct dpu_enc_phys_init_params *p); /** * dpu_encoder_phys_cmd_init - Construct a new command mode physical encoder + * @dev: Corresponding device for devres management * @p: Pointer to init params structure * Return: Error code or newly allocated encoder */ -struct dpu_encoder_phys *dpu_encoder_phys_cmd_init( +struct dpu_encoder_phys *dpu_encoder_phys_cmd_init(struct drm_device *dev, struct dpu_enc_phys_init_params *p); /** * dpu_encoder_phys_wb_init - initialize writeback encoder + * @dev: Corresponding device for devres management * @init: Pointer to init info structure with initialization params */ -struct dpu_encoder_phys *dpu_encoder_phys_wb_init( +struct dpu_encoder_phys *dpu_encoder_phys_wb_init(struct drm_device *dev, struct dpu_enc_phys_init_params *p); /** diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c index b856c6286c85..2958b64e6e5e 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c @@ -13,6 +13,8 @@ #include "dpu_trace.h" #include "disp/msm_disp_snapshot.h" +#include + #define DPU_DEBUG_CMDENC(e, fmt, ...) DPU_DEBUG("enc%d intf%d " fmt, \ (e) && (e)->base.parent ? \ (e)->base.parent->base.id : -1, \ @@ -563,14 +565,6 @@ static void dpu_encoder_phys_cmd_disable(struct dpu_encoder_phys *phys_enc) phys_enc->enable_state = DPU_ENC_DISABLED; } -static void dpu_encoder_phys_cmd_destroy(struct dpu_encoder_phys *phys_enc) -{ -
[PATCH 13/13] drm/msm/dpu: use drmm-managed allocation for dpu_encoder_virt
It is incorrect to use devm-managed memory allocations for DRM data structures exposed to userspace. They should use drmm_ allocations. Change struct dpu_encoder allocation to use drmm_encoder_alloc(). This removes the need to perform any actions on encoder destruction. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 44 - 1 file changed, 7 insertions(+), 37 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index b42176ce4a3a..fef66c6cb488 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -443,23 +443,6 @@ int dpu_encoder_get_linecount(struct drm_encoder *drm_enc) return linecount; } -static void dpu_encoder_destroy(struct drm_encoder *drm_enc) -{ - struct dpu_encoder_virt *dpu_enc = NULL; - int i = 0; - - if (!drm_enc) { - DPU_ERROR("invalid encoder\n"); - return; - } - - dpu_enc = to_dpu_encoder_virt(drm_enc); - DPU_DEBUG_ENC(dpu_enc, "\n"); - - drm_encoder_cleanup(drm_enc); - mutex_destroy(_enc->enc_lock); -} - void dpu_encoder_helper_split_config( struct dpu_encoder_phys *phys_enc, enum dpu_intf interface) @@ -2365,7 +2348,6 @@ static const struct drm_encoder_helper_funcs dpu_encoder_helper_funcs = { }; static const struct drm_encoder_funcs dpu_encoder_funcs = { - .destroy = dpu_encoder_destroy, .late_register = dpu_encoder_late_register, .early_unregister = dpu_encoder_early_unregister, }; @@ -2376,21 +2358,14 @@ struct drm_encoder *dpu_encoder_init(struct drm_device *dev, { struct msm_drm_private *priv = dev->dev_private; struct dpu_kms *dpu_kms = to_dpu_kms(priv->kms); - struct drm_encoder *drm_enc = NULL; - struct dpu_encoder_virt *dpu_enc = NULL; + struct dpu_encoder_virt *dpu_enc; int ret = 0; - dpu_enc = devm_kzalloc(dev->dev, sizeof(*dpu_enc), GFP_KERNEL); + dpu_enc = drmm_encoder_alloc(dev, struct dpu_encoder_virt, base, +_encoder_funcs, drm_enc_mode, NULL); if (!dpu_enc) return ERR_PTR(-ENOMEM); - ret = drm_encoder_init(dev, _enc->base, _encoder_funcs, - drm_enc_mode, NULL); - if (ret) { - devm_kfree(dev->dev, dpu_enc); - return ERR_PTR(ret); - } - drm_encoder_helper_add(_enc->base, _encoder_helper_funcs); spin_lock_init(_enc->enc_spinlock); @@ -2399,8 +2374,10 @@ struct drm_encoder *dpu_encoder_init(struct drm_device *dev, mutex_init(_enc->rc_lock); ret = dpu_encoder_setup_display(dpu_enc, dpu_kms, disp_info); - if (ret) - goto fail; + if (ret) { + DPU_ERROR("failed to setup encoder\n"); + return ERR_PTR(-ENOMEM); + } atomic_set(_enc->frame_done_timeout_ms, 0); timer_setup(_enc->frame_done_timer, @@ -2426,13 +2403,6 @@ struct drm_encoder *dpu_encoder_init(struct drm_device *dev, DPU_DEBUG_ENC(dpu_enc, "created\n"); return _enc->base; - -fail: - DPU_ERROR("failed to create encoder\n"); - if (drm_enc) - dpu_encoder_destroy(drm_enc); - - return ERR_PTR(ret); } int dpu_encoder_wait_for_event(struct drm_encoder *drm_enc, -- 2.39.2
[PATCH 09/13] drm/msm/dpu: use drmm-managed allocation for dpu_plane
Change struct dpu_plane allocation to use drmm_universal_plane_alloc(). This removes the need to perform any actions on plane destruction. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 44 +-- 1 file changed, 9 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index f114efee1b57..bbf47151adde 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -1170,20 +1170,6 @@ static void dpu_plane_atomic_update(struct drm_plane *plane, } } -static void dpu_plane_destroy(struct drm_plane *plane) -{ - struct dpu_plane *pdpu = plane ? to_dpu_plane(plane) : NULL; - - DPU_DEBUG_PLANE(pdpu, "\n"); - - if (pdpu) { - /* this will destroy the states as well */ - drm_plane_cleanup(plane); - - kfree(pdpu); - } -} - static void dpu_plane_destroy_state(struct drm_plane *plane, struct drm_plane_state *state) { @@ -1353,7 +1339,6 @@ static bool dpu_plane_format_mod_supported(struct drm_plane *plane, static const struct drm_plane_funcs dpu_plane_funcs = { .update_plane = drm_atomic_helper_update_plane, .disable_plane = drm_atomic_helper_disable_plane, - .destroy = dpu_plane_destroy, .reset = dpu_plane_reset, .atomic_duplicate_state = dpu_plane_duplicate_state, .atomic_destroy_state = dpu_plane_destroy_state, @@ -1383,33 +1368,26 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev, uint32_t supported_rotations; int ret = -EINVAL; - /* create and zero local structure */ - pdpu = kzalloc(sizeof(*pdpu), GFP_KERNEL); - if (!pdpu) { - DPU_ERROR("[%u]failed to allocate local plane struct\n", pipe); - ret = -ENOMEM; - return ERR_PTR(ret); - } - - /* cache local stuff for later */ - plane = >base; - pdpu->pipe = pipe; - /* initialize underlying h/w driver */ pipe_hw = dpu_rm_get_sspp(>rm, pipe); if (!pipe_hw || !pipe_hw->cap || !pipe_hw->cap->sblk) { DPU_ERROR("[%u]SSPP is invalid\n", pipe); - goto clean_plane; + return ERR_CAST(pdpu); } format_list = pipe_hw->cap->sblk->format_list; num_formats = pipe_hw->cap->sblk->num_formats; - ret = drm_universal_plane_init(dev, plane, 0xff, _plane_funcs, + pdpu = drmm_universal_plane_alloc(dev, struct dpu_plane, base, + 0xff, _plane_funcs, format_list, num_formats, supported_format_modifiers, type, NULL); - if (ret) - goto clean_plane; + if (IS_ERR(pdpu)) + return ERR_CAST(pdpu); + + /* cache local stuff for later */ + plane = >base; + pdpu->pipe = pipe; pdpu->catalog = kms->catalog; @@ -1439,8 +1417,4 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev, DPU_DEBUG("%s created for pipe:%u id:%u\n", plane->name, pipe, plane->base.id); return plane; - -clean_plane: - kfree(pdpu); - return ERR_PTR(ret); } -- 2.39.2
[PATCH 12/13] drm/msm/dpu: drop dpu_encoder_phys_ops::destroy
Drop the dpu_encoder_phys_ops' destroy() callback. No phys backend implements it anymore, so it is useless. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c| 18 -- .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 2 -- 2 files changed, 20 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 7c2cd9ce8acd..b42176ce4a3a 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -456,24 +456,6 @@ static void dpu_encoder_destroy(struct drm_encoder *drm_enc) dpu_enc = to_dpu_encoder_virt(drm_enc); DPU_DEBUG_ENC(dpu_enc, "\n"); - mutex_lock(_enc->enc_lock); - - for (i = 0; i < dpu_enc->num_phys_encs; i++) { - struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i]; - - if (phys->ops.destroy) { - phys->ops.destroy(phys); - --dpu_enc->num_phys_encs; - dpu_enc->phys_encs[i] = NULL; - } - } - - if (dpu_enc->num_phys_encs) - DPU_ERROR_ENC(dpu_enc, "expected 0 num_phys_encs not %d\n", - dpu_enc->num_phys_encs); - dpu_enc->num_phys_encs = 0; - mutex_unlock(_enc->enc_lock); - drm_encoder_cleanup(drm_enc); mutex_destroy(_enc->enc_lock); } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h index 4fb0d95f3061..757ce58f958b 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h @@ -72,7 +72,6 @@ struct dpu_encoder_phys; * @enable:DRM Call. Enable a DRM mode. * @disable: DRM Call. Disable mode. * @atomic_check: DRM Call. Atomic check new DRM state. - * @destroy: DRM Call. Destroy and release resources. * @control_vblank_irq Register/Deregister for VBLANK IRQ * @wait_for_commit_done: Wait for hardware to have flushed the * current pending frames to hardware @@ -102,7 +101,6 @@ struct dpu_encoder_phys_ops { int (*atomic_check)(struct dpu_encoder_phys *encoder, struct drm_crtc_state *crtc_state, struct drm_connector_state *conn_state); - void (*destroy)(struct dpu_encoder_phys *encoder); int (*control_vblank_irq)(struct dpu_encoder_phys *enc, bool enable); int (*wait_for_commit_done)(struct dpu_encoder_phys *phys_enc); int (*wait_for_tx_complete)(struct dpu_encoder_phys *phys_enc); -- 2.39.2
[PATCH 07/13] drm/msm/dpu: drop unused dpu_plane::lock
The field dpu_plane::lock was never used for protecting any kind of data. Drop it now. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 6 -- 1 file changed, 6 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index c2aaaded07ed..aba5185e1d66 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -78,8 +78,6 @@ static const uint32_t qcom_compressed_supported_formats[] = { struct dpu_plane { struct drm_plane base; - struct mutex lock; - enum dpu_sspp pipe; uint32_t color_fill; @@ -1186,8 +1184,6 @@ static void dpu_plane_destroy(struct drm_plane *plane) if (pstate->r_pipe.sspp) _dpu_plane_set_qos_ctrl(plane, >r_pipe, false); - mutex_destroy(>lock); - /* this will destroy the states as well */ drm_plane_cleanup(plane); @@ -1447,8 +1443,6 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev, /* success! finalize initialization */ drm_plane_helper_add(plane, _plane_helper_funcs); - mutex_init(>lock); - DPU_DEBUG("%s created for pipe:%u id:%u\n", plane->name, pipe, plane->base.id); return plane; -- 2.39.2
[PATCH 10/13] drm/msm/dpu: use drmm-managed allocation for dpu_crtc
Change struct dpu_crtc allocation to use drmm_crtc_alloc_with_planes(). This removes the need to perform any actions on CRTC destruction. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 21 + 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c index 214229d11e3e..23a944e15109 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -51,17 +51,6 @@ static struct dpu_kms *_dpu_crtc_get_kms(struct drm_crtc *crtc) return to_dpu_kms(priv->kms); } -static void dpu_crtc_destroy(struct drm_crtc *crtc) -{ - struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc); - - if (!crtc) - return; - - drm_crtc_cleanup(crtc); - kfree(dpu_crtc); -} - static struct drm_encoder *get_encoder_from_crtc(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; @@ -1433,7 +1422,6 @@ static int dpu_crtc_late_register(struct drm_crtc *crtc) static const struct drm_crtc_funcs dpu_crtc_funcs = { .set_config = drm_atomic_helper_set_config, - .destroy = dpu_crtc_destroy, .page_flip = drm_atomic_helper_page_flip, .reset = dpu_crtc_reset, .atomic_duplicate_state = dpu_crtc_duplicate_state, @@ -1467,7 +1455,11 @@ struct drm_crtc *dpu_crtc_init(struct drm_device *dev, struct drm_plane *plane, struct dpu_crtc *dpu_crtc = NULL; int i, ret; - dpu_crtc = kzalloc(sizeof(*dpu_crtc), GFP_KERNEL); + dpu_crtc = drmm_crtc_alloc_with_planes(dev, struct dpu_crtc, base, + plane, cursor, + _crtc_funcs, + NULL); + if (!dpu_crtc) return ERR_PTR(-ENOMEM); @@ -1489,9 +1481,6 @@ struct drm_crtc *dpu_crtc_init(struct drm_device *dev, struct drm_plane *plane, dpu_crtc_frame_event_work); } - drm_crtc_init_with_planes(dev, crtc, plane, cursor, _crtc_funcs, - NULL); - drm_crtc_helper_add(crtc, _crtc_helper_funcs); if (dpu_kms->catalog->dspp_count) -- 2.39.2
[PATCH 05/13] drm/msm/dpu: use devres-managed allocation for MDP TOP
Use devm_kzalloc to create MDP TOP structure. This allows us to remove corresponding kfree and drop dpu_hw_mdp_destroy() function. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c | 17 +++-- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h | 8 +--- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c| 5 ++--- 3 files changed, 14 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c index cff48763ce25..481b373d9ccb 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c @@ -2,6 +2,8 @@ /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. */ +#include + #include "dpu_hwio.h" #include "dpu_hw_catalog.h" #include "dpu_hw_top.h" @@ -268,16 +270,17 @@ static void _setup_mdp_ops(struct dpu_hw_mdp_ops *ops, ops->intf_audio_select = dpu_hw_intf_audio_select; } -struct dpu_hw_mdp *dpu_hw_mdptop_init(const struct dpu_mdp_cfg *cfg, - void __iomem *addr, - const struct dpu_mdss_cfg *m) +struct dpu_hw_mdp *dpu_hw_mdptop_init(struct drm_device *dev, + const struct dpu_mdp_cfg *cfg, + void __iomem *addr, + const struct dpu_mdss_cfg *m) { struct dpu_hw_mdp *mdp; if (!addr) return ERR_PTR(-EINVAL); - mdp = kzalloc(sizeof(*mdp), GFP_KERNEL); + mdp = drmm_kzalloc(dev, sizeof(*mdp), GFP_KERNEL); if (!mdp) return ERR_PTR(-ENOMEM); @@ -292,9 +295,3 @@ struct dpu_hw_mdp *dpu_hw_mdptop_init(const struct dpu_mdp_cfg *cfg, return mdp; } - -void dpu_hw_mdp_destroy(struct dpu_hw_mdp *mdp) -{ - kfree(mdp); -} - diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h index 8b1463d2b2f0..6f3dc98087df 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h @@ -145,13 +145,15 @@ struct dpu_hw_mdp { /** * dpu_hw_mdptop_init - initializes the top driver for the passed config + * @dev: Corresponding device for devres management * @cfg: MDP TOP configuration from catalog * @addr: Mapped register io address of MDP * @m:Pointer to mdss catalog data */ -struct dpu_hw_mdp *dpu_hw_mdptop_init(const struct dpu_mdp_cfg *cfg, - void __iomem *addr, - const struct dpu_mdss_cfg *m); +struct dpu_hw_mdp *dpu_hw_mdptop_init(struct drm_device *dev, + const struct dpu_mdp_cfg *cfg, + void __iomem *addr, + const struct dpu_mdss_cfg *m); void dpu_hw_mdp_destroy(struct dpu_hw_mdp *mdp); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index f7723f89cbbc..48c3f8b6b88f 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -822,8 +822,6 @@ static void _dpu_kms_hw_destroy(struct dpu_kms *dpu_kms) dpu_kms->catalog = NULL; - if (dpu_kms->hw_mdp) - dpu_hw_mdp_destroy(dpu_kms->hw_mdp); dpu_kms->hw_mdp = NULL; } @@ -1051,7 +1049,8 @@ static int dpu_kms_hw_init(struct msm_kms *kms) dpu_kms->rm_init = true; - dpu_kms->hw_mdp = dpu_hw_mdptop_init(dpu_kms->catalog->mdp, + dpu_kms->hw_mdp = dpu_hw_mdptop_init(dev, +dpu_kms->catalog->mdp, dpu_kms->mmio, dpu_kms->catalog); if (IS_ERR(dpu_kms->hw_mdp)) { -- 2.39.2
[PATCH 08/13] drm/msm/dpu: remove QoS teardown on plane destruction
There is little point in disabling QoS on plane destruction: it happens during DPU device destruction process, after which there will be no running planes. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 7 --- 1 file changed, 7 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index aba5185e1d66..f114efee1b57 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -1173,17 +1173,10 @@ static void dpu_plane_atomic_update(struct drm_plane *plane, static void dpu_plane_destroy(struct drm_plane *plane) { struct dpu_plane *pdpu = plane ? to_dpu_plane(plane) : NULL; - struct dpu_plane_state *pstate; DPU_DEBUG_PLANE(pdpu, "\n"); if (pdpu) { - pstate = to_dpu_plane_state(plane->state); - _dpu_plane_set_qos_ctrl(plane, >pipe, false); - - if (pstate->r_pipe.sspp) - _dpu_plane_set_qos_ctrl(plane, >r_pipe, false); - /* this will destroy the states as well */ drm_plane_cleanup(plane); -- 2.39.2
[PATCH 06/13] drm/msm/dpu: use devres-managed allocation for HW blocks
Use devm_kzalloc to create HW block structure. This allows us to remove corresponding kfree and drop all dpu_hw_*_destroy() functions as well as dpu_rm_destroy(), which becomes empty afterwards. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c| 19 ++-- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h| 16 ++-- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c| 12 ++- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h| 10 ++- .../gpu/drm/msm/disp/dpu1/dpu_hw_dsc_1_2.c| 7 +- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c | 16 ++-- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h | 12 +-- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c | 15 ++-- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h | 12 +-- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c | 14 ++- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h | 12 +-- .../gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.c| 14 ++- .../gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.h| 13 +-- .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c | 14 ++- .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h | 13 +-- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c | 15 ++-- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h | 7 +- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c | 14 ++- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h | 12 +-- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 8 +- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 1 - drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c| 90 +++ drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h| 11 +-- 23 files changed, 119 insertions(+), 238 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c index c278fb9d2b5b..d22e3f11ae34 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c @@ -4,6 +4,9 @@ */ #include + +#include + #include "dpu_hwio.h" #include "dpu_hw_ctl.h" #include "dpu_kms.h" @@ -674,14 +677,15 @@ static void _setup_ctl_ops(struct dpu_hw_ctl_ops *ops, ops->set_active_pipes = dpu_hw_ctl_set_fetch_pipe_active; }; -struct dpu_hw_ctl *dpu_hw_ctl_init(const struct dpu_ctl_cfg *cfg, - void __iomem *addr, - u32 mixer_count, - const struct dpu_lm_cfg *mixer) +struct dpu_hw_ctl *dpu_hw_ctl_init(struct drm_device *dev, + const struct dpu_ctl_cfg *cfg, + void __iomem *addr, + u32 mixer_count, + const struct dpu_lm_cfg *mixer) { struct dpu_hw_ctl *c; - c = kzalloc(sizeof(*c), GFP_KERNEL); + c = drmm_kzalloc(dev, sizeof(*c), GFP_KERNEL); if (!c) return ERR_PTR(-ENOMEM); @@ -696,8 +700,3 @@ struct dpu_hw_ctl *dpu_hw_ctl_init(const struct dpu_ctl_cfg *cfg, return c; } - -void dpu_hw_ctl_destroy(struct dpu_hw_ctl *ctx) -{ - kfree(ctx); -} diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h index 1c242298ff2e..279ebd8dfbff 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h @@ -274,20 +274,16 @@ static inline struct dpu_hw_ctl *to_dpu_hw_ctl(struct dpu_hw_blk *hw) /** * dpu_hw_ctl_init() - Initializes the ctl_path hw driver object. * Should be called before accessing any ctl_path register. + * @dev: Corresponding device for devres management * @cfg: ctl_path catalog entry for which driver object is required * @addr: mapped register io address of MDP * @mixer_count: Number of mixers in @mixer * @mixer: Pointer to an array of Layer Mixers defined in the catalog */ -struct dpu_hw_ctl *dpu_hw_ctl_init(const struct dpu_ctl_cfg *cfg, - void __iomem *addr, - u32 mixer_count, - const struct dpu_lm_cfg *mixer); - -/** - * dpu_hw_ctl_destroy(): Destroys ctl driver context - * should be called to free the context - */ -void dpu_hw_ctl_destroy(struct dpu_hw_ctl *ctx); +struct dpu_hw_ctl *dpu_hw_ctl_init(struct drm_device *dev, + const struct dpu_ctl_cfg *cfg, + void __iomem *addr, + u32 mixer_count, + const struct dpu_lm_cfg *mixer); #endif /*_DPU_HW_CTL_H */ diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c index 509dbaa51d87..5e9aad1b2aa2 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c @@ -3,6 +3,8 @@ * Copyright (c) 2020-2022, Linaro Limited */ +#include + #include #include "dpu_kms.h" @@ -188,12 +190,13 @@ static void _setup_dsc_ops(struct dpu_hw_dsc_ops *ops, ops->dsc_bind_pingpong_blk = dpu_hw_dsc_bind_pingpong_blk; }; -struct dpu_hw_dsc *dpu_hw_dsc_init(const struct dpu_dsc_cfg *cfg, +struct
[PATCH 04/13] drm/msm/dpu: use devres-managed allocation for VBIF data
Use devm_kzalloc to create VBIF data structure. This allows us to remove corresponding kfree and drop dpu_hw_intr_destroy() function. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.c | 14 ++ drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h | 8 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 11 +++ 3 files changed, 13 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.c index a5121a50b2bb..98e34afde2d2 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.c @@ -2,6 +2,8 @@ /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. */ +#include + #include "dpu_hwio.h" #include "dpu_hw_catalog.h" #include "dpu_hw_vbif.h" @@ -211,12 +213,13 @@ static void _setup_vbif_ops(struct dpu_hw_vbif_ops *ops, ops->set_write_gather_en = dpu_hw_set_write_gather_en; } -struct dpu_hw_vbif *dpu_hw_vbif_init(const struct dpu_vbif_cfg *cfg, - void __iomem *addr) +struct dpu_hw_vbif *dpu_hw_vbif_init(struct drm_device *dev, +const struct dpu_vbif_cfg *cfg, +void __iomem *addr) { struct dpu_hw_vbif *c; - c = kzalloc(sizeof(*c), GFP_KERNEL); + c = drmm_kzalloc(dev, sizeof(*c), GFP_KERNEL); if (!c) return ERR_PTR(-ENOMEM); @@ -234,8 +237,3 @@ struct dpu_hw_vbif *dpu_hw_vbif_init(const struct dpu_vbif_cfg *cfg, return c; } - -void dpu_hw_vbif_destroy(struct dpu_hw_vbif *vbif) -{ - kfree(vbif); -} diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h index 7e10d2a172b4..e2b4307500e4 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h @@ -108,12 +108,12 @@ struct dpu_hw_vbif { /** * dpu_hw_vbif_init() - Initializes the VBIF driver for the passed * VBIF catalog entry. + * @dev: Corresponding device for devres management * @cfg: VBIF catalog entry for which driver object is required * @addr: Mapped register io address of MDSS */ -struct dpu_hw_vbif *dpu_hw_vbif_init(const struct dpu_vbif_cfg *cfg, - void __iomem *addr); - -void dpu_hw_vbif_destroy(struct dpu_hw_vbif *vbif); +struct dpu_hw_vbif *dpu_hw_vbif_init(struct drm_device *dev, +const struct dpu_vbif_cfg *cfg, +void __iomem *addr); #endif /*_DPU_HW_VBIF_H */ diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index ef232dc838c7..f7723f89cbbc 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -812,13 +812,8 @@ static void _dpu_kms_hw_destroy(struct dpu_kms *dpu_kms) /* safe to call these more than once during shutdown */ _dpu_kms_mmu_destroy(dpu_kms); - if (dpu_kms->catalog) { - for (i = 0; i < ARRAY_SIZE(dpu_kms->hw_vbif); i++) { - if (dpu_kms->hw_vbif[i]) { - dpu_hw_vbif_destroy(dpu_kms->hw_vbif[i]); - dpu_kms->hw_vbif[i] = NULL; - } - } + for (i = 0; i < ARRAY_SIZE(dpu_kms->hw_vbif); i++) { + dpu_kms->hw_vbif[i] = NULL; } if (dpu_kms->rm_init) @@ -1070,7 +1065,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms) struct dpu_hw_vbif *hw; const struct dpu_vbif_cfg *vbif = _kms->catalog->vbif[i]; - hw = dpu_hw_vbif_init(vbif, dpu_kms->vbif[vbif->id]); + hw = dpu_hw_vbif_init(dev, vbif, dpu_kms->vbif[vbif->id]); if (IS_ERR(hw)) { rc = PTR_ERR(hw); DPU_ERROR("failed to init vbif %d: %d\n", vbif->id, rc); -- 2.39.2
[PATCH 03/13] drm/msm/dpu: use devres-managed allocation for interrupts data
Use devm_kzalloc to create interrupts data structure. This allows us to remove corresponding kfree and drop dpu_hw_intr_destroy() function. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c | 14 ++ drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h | 11 --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 4 +--- 3 files changed, 11 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c index 5e2d68ebb113..945f34736206 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c @@ -6,6 +6,8 @@ #include #include +#include + #include "dpu_core_irq.h" #include "dpu_kms.h" #include "dpu_hw_interrupts.h" @@ -441,8 +443,9 @@ static void __intr_offset(const struct dpu_mdss_cfg *m, hw->blk_addr = addr + m->mdp[0].base; } -struct dpu_hw_intr *dpu_hw_intr_init(void __iomem *addr, - const struct dpu_mdss_cfg *m) +struct dpu_hw_intr *dpu_hw_intr_init(struct drm_device *dev, +void __iomem *addr, +const struct dpu_mdss_cfg *m) { struct dpu_hw_intr *intr; int nirq = MDP_INTR_MAX * 32; @@ -450,7 +453,7 @@ struct dpu_hw_intr *dpu_hw_intr_init(void __iomem *addr, if (!addr || !m) return ERR_PTR(-EINVAL); - intr = kzalloc(struct_size(intr, irq_tbl, nirq), GFP_KERNEL); + intr = drmm_kzalloc(dev, struct_size(intr, irq_tbl, nirq), GFP_KERNEL); if (!intr) return ERR_PTR(-ENOMEM); @@ -465,11 +468,6 @@ struct dpu_hw_intr *dpu_hw_intr_init(void __iomem *addr, return intr; } -void dpu_hw_intr_destroy(struct dpu_hw_intr *intr) -{ - kfree(intr); -} - int dpu_core_irq_register_callback(struct dpu_kms *dpu_kms, int irq_idx, void (*irq_cb)(void *arg, int irq_idx), void *irq_arg) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h index 1f2dabc54c22..b0d7bb073203 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h @@ -70,15 +70,12 @@ struct dpu_hw_intr { /** * dpu_hw_intr_init(): Initializes the interrupts hw object + * @dev: Corresponding device for devres management * @addr: mapped register io address of MDP * @m:pointer to MDSS catalog data */ -struct dpu_hw_intr *dpu_hw_intr_init(void __iomem *addr, - const struct dpu_mdss_cfg *m); +struct dpu_hw_intr *dpu_hw_intr_init(struct drm_device *dev, +void __iomem *addr, +const struct dpu_mdss_cfg *m); -/** - * dpu_hw_intr_destroy(): Cleanup interrutps hw object - * @intr: pointer to interrupts hw object - */ -void dpu_hw_intr_destroy(struct dpu_hw_intr *intr); #endif diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index 85b8c9cc99ef..ef232dc838c7 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -807,8 +807,6 @@ static void _dpu_kms_hw_destroy(struct dpu_kms *dpu_kms) { int i; - if (dpu_kms->hw_intr) - dpu_hw_intr_destroy(dpu_kms->hw_intr); dpu_kms->hw_intr = NULL; /* safe to call these more than once during shutdown */ @@ -1095,7 +1093,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms) goto err_pm_put; } - dpu_kms->hw_intr = dpu_hw_intr_init(dpu_kms->mmio, dpu_kms->catalog); + dpu_kms->hw_intr = dpu_hw_intr_init(dev, dpu_kms->mmio, dpu_kms->catalog); if (IS_ERR(dpu_kms->hw_intr)) { rc = PTR_ERR(dpu_kms->hw_intr); DPU_ERROR("hw_intr init failed: %d\n", rc); -- 2.39.2
[PATCH 01/13] drm/msm/dpu: cleanup dpu_kms_hw_init error path
It was noticed that dpu_kms_hw_init()'s error path contains several labels which point to the same code path. Replace all of them with a single label. Suggested-by: Konrad Dybcio Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 21 + 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index c11b3ab572ab..e7ac02e92f42 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -1037,7 +1037,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms) if (!dpu_kms->catalog) { DPU_ERROR("device config not known!\n"); rc = -EINVAL; - goto power_error; + goto err_pm_put; } /* @@ -1047,13 +1047,13 @@ static int dpu_kms_hw_init(struct msm_kms *kms) rc = _dpu_kms_mmu_init(dpu_kms); if (rc) { DPU_ERROR("dpu_kms_mmu_init failed: %d\n", rc); - goto power_error; + goto err_pm_put; } rc = dpu_rm_init(_kms->rm, dpu_kms->catalog, dpu_kms->mmio); if (rc) { DPU_ERROR("rm init failed: %d\n", rc); - goto power_error; + goto err_pm_put; } dpu_kms->rm_init = true; @@ -1065,7 +1065,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms) rc = PTR_ERR(dpu_kms->hw_mdp); DPU_ERROR("failed to get hw_mdp: %d\n", rc); dpu_kms->hw_mdp = NULL; - goto power_error; + goto err_pm_put; } for (i = 0; i < dpu_kms->catalog->vbif_count; i++) { @@ -1076,7 +1076,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms) if (IS_ERR(hw)) { rc = PTR_ERR(hw); DPU_ERROR("failed to init vbif %d: %d\n", vbif->id, rc); - goto power_error; + goto err_pm_put; } dpu_kms->hw_vbif[vbif->id] = hw; @@ -1092,7 +1092,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms) rc = dpu_core_perf_init(_kms->perf, dpu_kms->catalog->perf, max_core_clk_rate); if (rc) { DPU_ERROR("failed to init perf %d\n", rc); - goto perf_err; + goto err_pm_put; } dpu_kms->hw_intr = dpu_hw_intr_init(dpu_kms->mmio, dpu_kms->catalog); @@ -1100,7 +1100,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms) rc = PTR_ERR(dpu_kms->hw_intr); DPU_ERROR("hw_intr init failed: %d\n", rc); dpu_kms->hw_intr = NULL; - goto hw_intr_init_err; + goto err_pm_put; } dev->mode_config.min_width = 0; @@ -1125,7 +1125,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms) rc = _dpu_kms_drm_obj_init(dpu_kms); if (rc) { DPU_ERROR("modeset init failed: %d\n", rc); - goto drm_obj_init_err; + goto err_pm_put; } dpu_vbif_init_memtypes(dpu_kms); @@ -1134,10 +1134,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms) return 0; -drm_obj_init_err: -hw_intr_init_err: -perf_err: -power_error: +err_pm_put: pm_runtime_put_sync(_kms->pdev->dev); error: _dpu_kms_hw_destroy(dpu_kms); -- 2.39.2
[PATCH 02/13] drm/msm/dpu: remove IS_ERR_OR_NULL for dpu_hw_intr_init() error handling
Using IS_ERR_OR_NULL() together with PTR_ERR() is a typical mistake. If the value is NULL, then the function will return 0 instead of a proper return code. Replace IS_ERR_OR_NULL() with IS_ERR() in the dpu_hw_intr_init() error check. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index e7ac02e92f42..85b8c9cc99ef 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -1096,7 +1096,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms) } dpu_kms->hw_intr = dpu_hw_intr_init(dpu_kms->mmio, dpu_kms->catalog); - if (IS_ERR_OR_NULL(dpu_kms->hw_intr)) { + if (IS_ERR(dpu_kms->hw_intr)) { rc = PTR_ERR(dpu_kms->hw_intr); DPU_ERROR("hw_intr init failed: %d\n", rc); dpu_kms->hw_intr = NULL; -- 2.39.2
[PATCH 00/13] drm/msm/dpu: use managed memory allocations
In a lots of places in DPU driver memory is allocated by using the kzalloc and then manually freed using kfree. However thes memory chunks have a well-defined life cycle. They are either a part of the driver's runtime and can be devm_kzalloc'ed or are exposed to userspace via the DRM objects and thus can be drmm_alloc'ed. Implement corresponding runtime resource manangement for the DPU driver. Dependencies: [1]. [1] https://patchwork.freedesktop.org/series/118839/ Dmitry Baryshkov (13): drm/msm/dpu: cleanup dpu_kms_hw_init error path drm/msm/dpu: remove IS_ERR_OR_NULL for dpu_hw_intr_init() error handling drm/msm/dpu: use devres-managed allocation for interrupts data drm/msm/dpu: use devres-managed allocation for VBIF data drm/msm/dpu: use devres-managed allocation for MDP TOP drm/msm/dpu: use devres-managed allocation for HW blocks drm/msm/dpu: drop unused dpu_plane::lock drm/msm/dpu: remove QoS teardown on plane destruction drm/msm/dpu: use drmm-managed allocation for dpu_plane drm/msm/dpu: use drmm-managed allocation for dpu_crtc drm/msm/dpu: use drmm-managed allocation for dpu_encoder_phys drm/msm/dpu: drop dpu_encoder_phys_ops::destroy drm/msm/dpu: use drmm-managed allocation for dpu_encoder_virt drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 21 ++--- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 71 +++ .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 10 +-- .../drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c | 15 +--- .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 13 +-- .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 21 + drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c| 19 ++-- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h| 16 ++-- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c| 12 ++- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h| 10 ++- .../gpu/drm/msm/disp/dpu1/dpu_hw_dsc_1_2.c| 7 +- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c | 16 ++-- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h | 12 +-- .../gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c | 14 ++- .../gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h | 11 +-- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c | 15 ++-- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h | 12 +-- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c | 14 ++- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h | 12 +-- .../gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.c| 14 ++- .../gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.h| 13 +-- .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c | 14 ++- .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h | 13 +-- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c | 15 ++-- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h | 7 +- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c| 17 ++-- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h| 8 +- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.c | 14 ++- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h | 8 +- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c | 14 ++- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h | 12 +-- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 51 --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 1 - drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 57 ++-- drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c| 90 +++ drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h| 11 +-- 36 files changed, 210 insertions(+), 470 deletions(-) -- 2.39.2
Re: [PATCH v3] drm/virtio: conditionally allocate virtio_gpu_fence
On 7/7/23 20:59, Gurchetan Singh wrote: /// >>> Previously, when VIRTGPU_EXECBUF_RING_IDX flag wasn't specified, the >>> fence event was created for a default ring_idx=0. Now you changed this >>> behaviour and event will never be created without >>> VIRTGPU_EXECBUF_RING_IDX flag being set. > > ring_idx = 0 is fine, but without VIRTGPU_EXECBUF_RING_IDX that means > the global timeline. > > It's an additional check for where the userspace specifies they want > to use per-context fencing and polling, but actually uses the global > timeline. Userspace never does this since it wouldn't work, so it's a > bit of a pathological edge case check than any UAPI change. > >>> >>> Could you please point me at the corresponding userspace code that polls >>> DRM FD fence event? > > https://chromium.googlesource.com/chromiumos/platform2/+/HEAD/vm_tools/sommelier/virtualization/virtgpu_channel.cc#216 > > Used with the following flow: > > https://crosvm.dev/book/devices/wayland.html > > If you wish to test, please do apply this change: > > https://chromium-review.googlesource.com/c/chromiumos/platform2/+/4605854 Thanks for the links! I tested v2 with sommelier, though wasn't aware about CL4605854 and alternatives to sommelier >>> It's unclear whether there is a possible userspace regression here or >>> not. If there is no regression, then in general such behavioural changes >>> should be done in a separate commit having detailed description >>> explaining why behaviour changes. > > Sommelier isn't formally packaged yet in the Linux distro style and it > always specifies RING_IDX when polling, so no regressions here. Maybe > a separate commit is overkill (since the 2nd commit would delete the > newly added checks), what about just more detail in the commit > message? More detail will be fine >> I see that venus does the polling and ring_idx_mask is a >> context-specific param, hence it's irrelevant to a generic ctx 0. Still >> it's now necessary to specify the EXECBUF_RING_IDX flag even if ctx has >> one ring, which is UAPI change. > > It doesn't seem like venus enables POLL_RINGS_MASK to poll since that > param is zero? > > https://gitlab.freedesktop.org/mesa/mesa/-/blob/main/src/virtio/vulkan/vn_renderer_virtgpu.c#L617 Indeed, good catch -- Best regards, Dmitry
[PATCH v3 08/11] drm/msm/dpu: remove unused fields from struct dpu_core_perf
Remove dpu_core_perf::dev and dpu_core_perf::debugfs_root fields, they are not used by the code. Reviewed-by: Konrad Dybcio Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c | 3 --- drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h | 6 -- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 2 +- 3 files changed, 1 insertion(+), 10 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c index 8db97583ef18..afd75750380c 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c @@ -497,15 +497,12 @@ void dpu_core_perf_destroy(struct dpu_core_perf *perf) perf->max_core_clk_rate = 0; perf->core_clk = NULL; - perf->dev = NULL; } int dpu_core_perf_init(struct dpu_core_perf *perf, - struct drm_device *dev, const struct dpu_perf_cfg *perf_cfg, struct clk *core_clk) { - perf->dev = dev; perf->perf_cfg = perf_cfg; perf->core_clk = core_clk; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h index f4b84e67138c..e718d523ff30 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h @@ -36,8 +36,6 @@ struct dpu_core_perf_tune { /** * struct dpu_core_perf - definition of core performance context - * @dev: Pointer to drm device - * @debugfs_root: top level debug folder * @perf_cfg: Platform-specific performance configuration * @core_clk: Pointer to the core clock * @core_clk_rate: current core clock rate @@ -49,8 +47,6 @@ struct dpu_core_perf_tune { * @fix_core_ab_vote: fixed core ab vote in bps used in mode 2 */ struct dpu_core_perf { - struct drm_device *dev; - struct dentry *debugfs_root; const struct dpu_perf_cfg *perf_cfg; struct clk *core_clk; u64 core_clk_rate; @@ -95,12 +91,10 @@ void dpu_core_perf_destroy(struct dpu_core_perf *perf); /** * dpu_core_perf_init - initialize the given core performance context * @perf: Pointer to core performance context - * @dev: Pointer to drm device * @perf_cfg: Pointer to platform performance configuration * @core_clk: pointer to core clock */ int dpu_core_perf_init(struct dpu_core_perf *perf, - struct drm_device *dev, const struct dpu_perf_cfg *perf_cfg, struct clk *core_clk); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index 6e62606e32de..631b6b679bae 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -1115,7 +1115,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms) dpu_kms->hw_vbif[vbif->id] = hw; } - rc = dpu_core_perf_init(_kms->perf, dev, dpu_kms->catalog->perf, + rc = dpu_core_perf_init(_kms->perf, dpu_kms->catalog->perf, msm_clk_bulk_get_clock(dpu_kms->clocks, dpu_kms->num_clocks, "core")); if (rc) { DPU_ERROR("failed to init perf %d\n", rc); -- 2.39.2
[PATCH v3 09/11] drm/msm/dpu: core_perf: remove extra clk_round_rate() call
The dev_pm_opp_set_rate() already contains a call for clk_round_rate for the passed value. Stop calling it manually from _dpu_core_perf_get_core_clk_rate(). It is slightly incorrect to call it this way, as we should round the final calculated clock rate rather than rounding all the intermediate values. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c index afd75750380c..a570810c9254 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c @@ -299,8 +299,6 @@ static u64 _dpu_core_perf_get_core_clk_rate(struct dpu_kms *kms) dpu_cstate = to_dpu_crtc_state(crtc->state); clk_rate = max(dpu_cstate->new_perf.core_clk_rate, clk_rate); - clk_rate = clk_round_rate(kms->perf.core_clk, - clk_rate); } } -- 2.39.2
[PATCH v3 11/11] drm/msm/dpu: drop dpu_core_perf_destroy()
This function does nothing, just clears one struct field. Drop it now. Acked-by: Konrad Dybcio Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c | 10 -- drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h | 6 -- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 1 - 3 files changed, 17 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c index e9d71c0855df..adb932b0f49c 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c @@ -486,16 +486,6 @@ int dpu_core_perf_debugfs_init(struct dpu_kms *dpu_kms, struct dentry *parent) } #endif -void dpu_core_perf_destroy(struct dpu_core_perf *perf) -{ - if (!perf) { - DPU_ERROR("invalid parameters\n"); - return; - } - - perf->max_core_clk_rate = 0; -} - int dpu_core_perf_init(struct dpu_core_perf *perf, const struct dpu_perf_cfg *perf_cfg, unsigned long max_core_clk_rate) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h index 8cc55752db5e..4186977390bd 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h @@ -78,12 +78,6 @@ int dpu_core_perf_crtc_update(struct drm_crtc *crtc, */ void dpu_core_perf_crtc_release_bw(struct drm_crtc *crtc); -/** - * dpu_core_perf_destroy - destroy the given core performance context - * @perf: Pointer to core performance context - */ -void dpu_core_perf_destroy(struct dpu_core_perf *perf); - /** * dpu_core_perf_init - initialize the given core performance context * @perf: Pointer to core performance context diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index f01b2278c01a..44b0daf70c4e 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -1171,7 +1171,6 @@ static int dpu_kms_hw_init(struct msm_kms *kms) return 0; drm_obj_init_err: - dpu_core_perf_destroy(_kms->perf); hw_intr_init_err: perf_err: power_error: -- 2.39.2
[PATCH v3 10/11] drm/msm/dpu: move max clock decision to dpu_kms.
dpu_core_perf should not make decisions on the maximum possible core clock rate. Pass the value from dpu_kms_hw_init(). Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c | 11 ++- drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h | 8 ++-- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 13 +++-- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c index a570810c9254..e9d71c0855df 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c @@ -494,21 +494,14 @@ void dpu_core_perf_destroy(struct dpu_core_perf *perf) } perf->max_core_clk_rate = 0; - perf->core_clk = NULL; } int dpu_core_perf_init(struct dpu_core_perf *perf, const struct dpu_perf_cfg *perf_cfg, - struct clk *core_clk) + unsigned long max_core_clk_rate) { perf->perf_cfg = perf_cfg; - perf->core_clk = core_clk; - - perf->max_core_clk_rate = clk_get_rate(core_clk); - if (!perf->max_core_clk_rate) { - DPU_DEBUG("optional max core clk rate, use default\n"); - perf->max_core_clk_rate = DPU_PERF_DEFAULT_MAX_CORE_CLK_RATE; - } + perf->max_core_clk_rate = max_core_clk_rate; return 0; } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h index e718d523ff30..8cc55752db5e 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h @@ -12,8 +12,6 @@ #include "dpu_hw_catalog.h" -#defineDPU_PERF_DEFAULT_MAX_CORE_CLK_RATE 41250 - /** * struct dpu_core_perf_params - definition of performance parameters * @max_per_pipe_ib: maximum instantaneous bandwidth request @@ -37,7 +35,6 @@ struct dpu_core_perf_tune { /** * struct dpu_core_perf - definition of core performance context * @perf_cfg: Platform-specific performance configuration - * @core_clk: Pointer to the core clock * @core_clk_rate: current core clock rate * @max_core_clk_rate: maximum allowable core clock rate * @perf_tune: debug control for performance tuning @@ -48,7 +45,6 @@ struct dpu_core_perf_tune { */ struct dpu_core_perf { const struct dpu_perf_cfg *perf_cfg; - struct clk *core_clk; u64 core_clk_rate; u64 max_core_clk_rate; struct dpu_core_perf_tune perf_tune; @@ -92,11 +88,11 @@ void dpu_core_perf_destroy(struct dpu_core_perf *perf); * dpu_core_perf_init - initialize the given core performance context * @perf: Pointer to core performance context * @perf_cfg: Pointer to platform performance configuration - * @core_clk: pointer to core clock + * @max_core_clk_rate: Maximum core clock rate */ int dpu_core_perf_init(struct dpu_core_perf *perf, const struct dpu_perf_cfg *perf_cfg, - struct clk *core_clk); + unsigned long max_core_clk_rate); struct dpu_kms; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index 631b6b679bae..f01b2278c01a 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -1011,11 +1011,14 @@ unsigned long dpu_kms_get_clk_rate(struct dpu_kms *dpu_kms, char *clock_name) return clk_get_rate(clk); } +#defineDPU_PERF_DEFAULT_MAX_CORE_CLK_RATE 41250 + static int dpu_kms_hw_init(struct msm_kms *kms) { struct dpu_kms *dpu_kms; struct drm_device *dev; int i, rc = -EINVAL; + unsigned long max_core_clk_rate; u32 core_rev; if (!kms) { @@ -1115,8 +1118,14 @@ static int dpu_kms_hw_init(struct msm_kms *kms) dpu_kms->hw_vbif[vbif->id] = hw; } - rc = dpu_core_perf_init(_kms->perf, dpu_kms->catalog->perf, - msm_clk_bulk_get_clock(dpu_kms->clocks, dpu_kms->num_clocks, "core")); + /* TODO: use the same max_freq as in dpu_kms_hw_init */ + max_core_clk_rate = dpu_kms_get_clk_rate(dpu_kms, "core"); + if (!max_core_clk_rate) { + DPU_DEBUG("max core clk rate not determined, using default\n"); + max_core_clk_rate = DPU_PERF_DEFAULT_MAX_CORE_CLK_RATE; + } + + rc = dpu_core_perf_init(_kms->perf, dpu_kms->catalog->perf, max_core_clk_rate); if (rc) { DPU_ERROR("failed to init perf %d\n", rc); goto perf_err; -- 2.39.2
[PATCH v3 06/11] drm/msm/dpu: drop the dpu_core_perf_crtc_update()'s stop_req param
The stop_req is true only in the dpu_crtc_disable() case, when crtc->enable has already been set to false. This renders the stop_req argument useless. Remove it completely. Reviewed-by: Abhinav Kumar Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c | 12 ++-- drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h | 3 +-- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 6 +++--- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c index 87bf4e5cb8e7..df1e47282777 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c @@ -315,7 +315,7 @@ static u64 _dpu_core_perf_get_core_clk_rate(struct dpu_kms *kms) } int dpu_core_perf_crtc_update(struct drm_crtc *crtc, - int params_changed, bool stop_req) + int params_changed) { struct dpu_core_perf_params *new, *old; bool update_bus = false, update_clk = false; @@ -339,13 +339,13 @@ int dpu_core_perf_crtc_update(struct drm_crtc *crtc, dpu_crtc = to_dpu_crtc(crtc); dpu_cstate = to_dpu_crtc_state(crtc->state); - DRM_DEBUG_ATOMIC("crtc:%d stop_req:%d core_clk:%llu\n", - crtc->base.id, stop_req, kms->perf.core_clk_rate); + DRM_DEBUG_ATOMIC("crtc:%d enabled:%d core_clk:%llu\n", + crtc->base.id, crtc->enabled, kms->perf.core_clk_rate); old = _crtc->cur_perf; new = _cstate->new_perf; - if (crtc->enabled && !stop_req) { + if (crtc->enabled) { /* * cases for bus bandwidth update. * 1. new bandwidth vote - "ab or ib vote" is higher @@ -378,7 +378,7 @@ int dpu_core_perf_crtc_update(struct drm_crtc *crtc, } trace_dpu_perf_crtc_update(crtc->base.id, new->bw_ctl, - new->core_clk_rate, stop_req, update_bus, update_clk); + new->core_clk_rate, !crtc->enabled, update_bus, update_clk); if (update_bus) { ret = _dpu_core_perf_crtc_update_bus(kms, crtc); @@ -398,7 +398,7 @@ int dpu_core_perf_crtc_update(struct drm_crtc *crtc, DRM_DEBUG_ATOMIC("clk:%llu\n", clk_rate); - trace_dpu_core_perf_update_clk(kms->dev, stop_req, clk_rate); + trace_dpu_core_perf_update_clk(kms->dev, !crtc->enabled, clk_rate); clk_rate = min(clk_rate, kms->perf.max_core_clk_rate); ret = dev_pm_opp_set_rate(>pdev->dev, clk_rate); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h index c965dfbc3007..c0097b67f9dd 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h @@ -75,11 +75,10 @@ int dpu_core_perf_crtc_check(struct drm_crtc *crtc, * dpu_core_perf_crtc_update - update performance of the given crtc * @crtc: Pointer to crtc * @params_changed: true if crtc parameters are modified - * @stop_req: true if this is a stop request * return: zero if success, or error code otherwise */ int dpu_core_perf_crtc_update(struct drm_crtc *crtc, - int params_changed, bool stop_req); + int params_changed); /** * dpu_core_perf_crtc_release_bw - release bandwidth of the given crtc diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c index 1edf2b6b0a26..8ce7586e2ddf 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -718,7 +718,7 @@ static void dpu_crtc_frame_event_cb(void *data, u32 event) void dpu_crtc_complete_commit(struct drm_crtc *crtc) { trace_dpu_crtc_complete_commit(DRMID(crtc)); - dpu_core_perf_crtc_update(crtc, 0, false); + dpu_core_perf_crtc_update(crtc, 0); _dpu_crtc_complete_flip(crtc); } @@ -884,7 +884,7 @@ static void dpu_crtc_atomic_flush(struct drm_crtc *crtc, return; /* update performance setting before crtc kickoff */ - dpu_core_perf_crtc_update(crtc, 1, false); + dpu_core_perf_crtc_update(crtc, 1); /* * Final plane updates: Give each plane a chance to complete all @@ -1100,7 +1100,7 @@ static void dpu_crtc_disable(struct drm_crtc *crtc, atomic_set(_crtc->frame_pending, 0); } - dpu_core_perf_crtc_update(crtc, 0, true); + dpu_core_perf_crtc_update(crtc, 0); drm_for_each_encoder_mask(encoder, crtc->dev, crtc->state->encoder_mask) dpu_encoder_register_frame_event_callback(encoder, NULL, NULL); -- 2.39.2
[PATCH v3 02/11] drm/msm/dpu: core_perf: extract bandwidth aggregation function
In preparation to refactoring the dpu_core_perf debugfs interface, extract the bandwidth aggregation function from _dpu_core_perf_crtc_update_bus(). Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c | 39 +++ 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c index 1d9d83d7b99e..333dcfe57800 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c @@ -206,33 +206,38 @@ int dpu_core_perf_crtc_check(struct drm_crtc *crtc, return 0; } -static int _dpu_core_perf_crtc_update_bus(struct dpu_kms *kms, - struct drm_crtc *crtc) +static void dpu_core_perf_aggregate(struct drm_device *ddev, + enum dpu_crtc_client_type curr_client_type, + struct dpu_core_perf_params *perf) { - struct dpu_core_perf_params perf = { 0 }; - enum dpu_crtc_client_type curr_client_type - = dpu_crtc_get_client_type(crtc); - struct drm_crtc *tmp_crtc; struct dpu_crtc_state *dpu_cstate; - int i, ret = 0; - u64 avg_bw; + struct drm_crtc *tmp_crtc; - drm_for_each_crtc(tmp_crtc, crtc->dev) { + drm_for_each_crtc(tmp_crtc, ddev) { if (tmp_crtc->enabled && - curr_client_type == - dpu_crtc_get_client_type(tmp_crtc)) { + curr_client_type == dpu_crtc_get_client_type(tmp_crtc)) { dpu_cstate = to_dpu_crtc_state(tmp_crtc->state); - perf.max_per_pipe_ib = max(perf.max_per_pipe_ib, - dpu_cstate->new_perf.max_per_pipe_ib); + perf->max_per_pipe_ib = max(perf->max_per_pipe_ib, + dpu_cstate->new_perf.max_per_pipe_ib); - perf.bw_ctl += dpu_cstate->new_perf.bw_ctl; + perf->bw_ctl += dpu_cstate->new_perf.bw_ctl; - DRM_DEBUG_ATOMIC("crtc=%d bw=%llu paths:%d\n", - tmp_crtc->base.id, - dpu_cstate->new_perf.bw_ctl, kms->num_paths); + DRM_DEBUG_ATOMIC("crtc=%d bw=%llu\n", +tmp_crtc->base.id, +dpu_cstate->new_perf.bw_ctl); } } +} + +static int _dpu_core_perf_crtc_update_bus(struct dpu_kms *kms, + struct drm_crtc *crtc) +{ + struct dpu_core_perf_params perf = { 0 }; + int i, ret = 0; + u64 avg_bw; + + dpu_core_perf_aggregate(crtc->dev, dpu_crtc_get_client_type(crtc), ); if (!kms->num_paths) return 0; -- 2.39.2