Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

drm: rcar-du: Don't leak device_link to CMM

The DU driver creates device_link instances between the DU and CMMs, but
never deletes them. Fix it by introducing a rcar_du_cmm structure to
group the CMM device and device_link, and deleting the links at cleanup
time.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Link: https://patch.msgid.link/20260323164526.2292491-5-laurent.pinchart+renesas@ideasonboard.com
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>

authored by

Laurent Pinchart and committed by
Tomi Valkeinen
3bce3fdd a93b8739

+35 -21
+8 -8
drivers/gpu/drm/renesas/rcar-du/rcar_du_crtc.c
··· 513 513 struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc); 514 514 struct rcar_cmm_config cmm_config = {}; 515 515 516 - if (!rcrtc->cmm) 516 + if (!rcrtc->cmm->dev) 517 517 return; 518 518 519 519 if (drm_lut) 520 520 cmm_config.lut.table = (struct drm_color_lut *)drm_lut->data; 521 521 522 - rcar_cmm_setup(rcrtc->cmm, &cmm_config); 522 + rcar_cmm_setup(rcrtc->cmm->dev, &cmm_config); 523 523 } 524 524 525 525 /* ----------------------------------------------------------------------------- ··· 667 667 if (rcar_du_has(rcrtc->dev, RCAR_DU_FEATURE_VSP1_SOURCE)) 668 668 rcar_du_vsp_disable(rcrtc); 669 669 670 - if (rcrtc->cmm) 671 - rcar_cmm_disable(rcrtc->cmm); 670 + if (rcrtc->cmm->dev) 671 + rcar_cmm_disable(rcrtc->cmm->dev); 672 672 673 673 /* 674 674 * Select switch sync mode. This stops display operation and configures ··· 726 726 struct rcar_du_crtc_state *rstate = to_rcar_crtc_state(crtc->state); 727 727 struct rcar_du_device *rcdu = rcrtc->dev; 728 728 729 - if (rcrtc->cmm) 730 - rcar_cmm_enable(rcrtc->cmm); 729 + if (rcrtc->cmm->dev) 730 + rcar_cmm_enable(rcrtc->cmm->dev); 731 731 rcar_du_crtc_get(rcrtc); 732 732 733 733 /* ··· 1300 1300 return ret; 1301 1301 1302 1302 /* CMM might be disabled for this CRTC. */ 1303 - if (rcdu->cmms[swindex]) { 1304 - rcrtc->cmm = rcdu->cmms[swindex]; 1303 + if (rcdu->cmms[swindex].dev) { 1304 + rcrtc->cmm = &rcdu->cmms[swindex]; 1305 1305 rgrp->cmms_mask |= BIT(hwindex % 2); 1306 1306 1307 1307 drm_mode_crtc_set_gamma_size(crtc, CM2_LUT_SIZE);
+2 -1
drivers/gpu/drm/renesas/rcar-du/rcar_du_crtc.h
··· 19 19 20 20 #include <media/vsp1.h> 21 21 22 + struct rcar_du_cmm; 22 23 struct rcar_du_group; 23 24 struct rcar_du_vsp; 24 25 ··· 66 65 unsigned int vblank_count; 67 66 68 67 struct rcar_du_group *group; 69 - struct device *cmm; 68 + struct rcar_du_cmm *cmm; 70 69 struct rcar_du_vsp *vsp; 71 70 unsigned int vsp_pipe; 72 71
+7 -1
drivers/gpu/drm/renesas/rcar-du/rcar_du_drv.h
··· 22 22 23 23 struct clk; 24 24 struct device; 25 + struct device_link; 25 26 struct drm_bridge; 26 27 struct drm_property; 27 28 struct rcar_du_device; ··· 89 88 unsigned int lvds_clk_mask; 90 89 }; 91 90 91 + struct rcar_du_cmm { 92 + struct device *dev; 93 + struct device_link *link; 94 + }; 95 + 92 96 #define RCAR_DU_MAX_CRTCS 4 93 97 #define RCAR_DU_MAX_GROUPS DIV_ROUND_UP(RCAR_DU_MAX_CRTCS, 2) 94 98 #define RCAR_DU_MAX_VSPS 4 ··· 112 106 unsigned int num_crtcs; 113 107 114 108 struct rcar_du_group groups[RCAR_DU_MAX_GROUPS]; 115 - struct device *cmms[RCAR_DU_MAX_CRTCS]; 109 + struct rcar_du_cmm cmms[RCAR_DU_MAX_CRTCS]; 116 110 struct rcar_du_vsp vsps[RCAR_DU_MAX_VSPS]; 117 111 struct drm_bridge *lvds[RCAR_DU_MAX_LVDS]; 118 112 struct drm_bridge *dsi[RCAR_DU_MAX_DSI];
+18 -11
drivers/gpu/drm/renesas/rcar-du/rcar_du_kms.c
··· 769 769 } 770 770 771 771 for (i = 0; i < cells; ++i) { 772 - struct device_node *cmm __free(device_node) = NULL; 772 + struct device_node *cmm_node __free(device_node) = NULL; 773 + struct rcar_du_cmm *cmm = &rcdu->cmms[i]; 773 774 struct platform_device *pdev; 774 - struct device_link *link; 775 775 int ret; 776 776 777 - cmm = of_parse_phandle(np, "renesas,cmms", i); 778 - if (!cmm) { 777 + cmm_node = of_parse_phandle(np, "renesas,cmms", i); 778 + if (!cmm_node) { 779 779 dev_err(rcdu->dev, 780 780 "Failed to parse 'renesas,cmms' property\n"); 781 781 return -EINVAL; 782 782 } 783 783 784 - if (!of_device_is_available(cmm)) 784 + if (!of_device_is_available(cmm_node)) 785 785 /* It's fine to have a phandle to a non-enabled CMM. */ 786 786 continue; 787 787 788 - pdev = of_find_device_by_node(cmm); 788 + pdev = of_find_device_by_node(cmm_node); 789 789 if (!pdev) { 790 790 dev_err(rcdu->dev, "No device found for CMM%u\n", i); 791 791 return -EINVAL; ··· 801 801 return ret == -ENODEV ? 0 : ret; 802 802 } 803 803 804 - rcdu->cmms[i] = &pdev->dev; 804 + cmm->dev = &pdev->dev; 805 805 806 806 /* 807 807 * Enforce suspend/resume ordering by making the CMM a provider 808 808 * of the DU: CMM is suspended after and resumed before the DU. 809 809 */ 810 - link = device_link_add(rcdu->dev, &pdev->dev, DL_FLAG_STATELESS); 811 - if (!link) { 810 + cmm->link = device_link_add(rcdu->dev, cmm->dev, 811 + DL_FLAG_STATELESS); 812 + if (!cmm->link) { 812 813 dev_err(rcdu->dev, 813 814 "Failed to create device link to CMM%u\n", i); 814 815 return -EINVAL; ··· 824 823 struct rcar_du_device *rcdu = to_rcar_du_device(dev); 825 824 unsigned int i; 826 825 827 - for (i = 0; i < ARRAY_SIZE(rcdu->cmms); ++i) 828 - put_device(rcdu->cmms[i]); 826 + for (i = 0; i < ARRAY_SIZE(rcdu->cmms); ++i) { 827 + struct rcar_du_cmm *cmm = &rcdu->cmms[i]; 828 + 829 + if (cmm->link) 830 + device_link_del(cmm->link); 831 + 832 + put_device(cmm->dev); 833 + } 829 834 } 830 835 831 836 int rcar_du_modeset_init(struct rcar_du_device *rcdu)