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.

Revert "drm/display: bridge_connector: get/put the stored bridges"

This reverts commit 2be300f9a0b6f6b0ae2a90be97e558ec0535be54.

The commit being reverted moved all the bridge_connector->bridge_*
assignments to just before the final successful return in order to handle
the bridge refcounting in a clean way.

This introduced a bug, because a bit before the successful return
drmm_connector_hdmi_cec_register() is called, which calls funcs->init()
which is drm_bridge_connector_hdmi_cec_init() which needs
bridge_connector->bridge_hdmi_cec to be set.

The reported bug may be fixed in a relatively simple way, but other similar
patterns are potentially present, so just revert the offending commit. A
different approach will be implemented.

Fixes: 2be300f9a0b6 ("drm/display: bridge_connector: get/put the stored bridges")
Reported-by: Marek Szyprowski <m.szyprowski@samsung.com>
Closes: https://lore.kernel.org/all/336fbfdd-c424-490e-b5d1-8ee84043dc80@samsung.com/
Reported-by: Naresh Kamboju <naresh.kamboju@linaro.org>
Closes: https://lore.kernel.org/r/CA+G9fYuKHp3QgPKjgFY3TfkDdh5Vf=Ae5pCW+eU41Bu=D7th2g@mail.gmail.com
Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Tested-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com> # db410c
Tested-by: Geert Uytterhoeven <geert+renesas@glider.be>
Tested-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
Tested-by: Tommaso Merciai <tommaso.merciai.xr@bp.renesas.com>
Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
Link: https://patch.msgid.link/20251017-drm-bridge-alloc-getput-bridge-connector-fix-hdmi_cec-v2-1-667abf6d47c0@bootlin.com
Signed-off-by: Luca Ceresoli <luca.ceresoli@bootlin.com>

+36 -78
+36 -78
drivers/gpu/drm/display/drm_bridge_connector.c
··· 618 618 * Bridge Connector Initialisation 619 619 */ 620 620 621 - static void drm_bridge_connector_put_bridges(struct drm_device *dev, void *data) 622 - { 623 - struct drm_bridge_connector *bridge_connector = (struct drm_bridge_connector *)data; 624 - 625 - drm_bridge_put(bridge_connector->bridge_edid); 626 - drm_bridge_put(bridge_connector->bridge_hpd); 627 - drm_bridge_put(bridge_connector->bridge_detect); 628 - drm_bridge_put(bridge_connector->bridge_modes); 629 - drm_bridge_put(bridge_connector->bridge_hdmi); 630 - drm_bridge_put(bridge_connector->bridge_hdmi_audio); 631 - drm_bridge_put(bridge_connector->bridge_dp_audio); 632 - drm_bridge_put(bridge_connector->bridge_hdmi_cec); 633 - } 634 - 635 621 /** 636 622 * drm_bridge_connector_init - Initialise a connector for a chain of bridges 637 623 * @drm: the DRM device ··· 638 652 struct drm_bridge_connector *bridge_connector; 639 653 struct drm_connector *connector; 640 654 struct i2c_adapter *ddc = NULL; 641 - struct drm_bridge *panel_bridge __free(drm_bridge_put) = NULL; 642 - struct drm_bridge *bridge_edid __free(drm_bridge_put) = NULL; 643 - struct drm_bridge *bridge_hpd __free(drm_bridge_put) = NULL; 644 - struct drm_bridge *bridge_detect __free(drm_bridge_put) = NULL; 645 - struct drm_bridge *bridge_modes __free(drm_bridge_put) = NULL; 646 - struct drm_bridge *bridge_hdmi __free(drm_bridge_put) = NULL; 647 - struct drm_bridge *bridge_hdmi_audio __free(drm_bridge_put) = NULL; 648 - struct drm_bridge *bridge_dp_audio __free(drm_bridge_put) = NULL; 649 - struct drm_bridge *bridge_hdmi_cec __free(drm_bridge_put) = NULL; 655 + struct drm_bridge *panel_bridge = NULL; 650 656 unsigned int supported_formats = BIT(HDMI_COLORSPACE_RGB); 651 657 unsigned int max_bpc = 8; 652 658 bool support_hdcp = false; ··· 648 670 bridge_connector = drmm_kzalloc(drm, sizeof(*bridge_connector), GFP_KERNEL); 649 671 if (!bridge_connector) 650 672 return ERR_PTR(-ENOMEM); 651 - 652 - ret = drmm_add_action(drm, drm_bridge_connector_put_bridges, bridge_connector); 653 - if (ret) 654 - return ERR_PTR(ret); 655 673 656 674 bridge_connector->encoder = encoder; 657 675 ··· 672 698 if (!bridge->ycbcr_420_allowed) 673 699 connector->ycbcr_420_allowed = false; 674 700 675 - if (bridge->ops & DRM_BRIDGE_OP_EDID) { 676 - drm_bridge_put(bridge_edid); 677 - bridge_edid = drm_bridge_get(bridge); 678 - } 679 - if (bridge->ops & DRM_BRIDGE_OP_HPD) { 680 - drm_bridge_put(bridge_hpd); 681 - bridge_hpd = drm_bridge_get(bridge); 682 - } 683 - if (bridge->ops & DRM_BRIDGE_OP_DETECT) { 684 - drm_bridge_put(bridge_detect); 685 - bridge_detect = drm_bridge_get(bridge); 686 - } 687 - if (bridge->ops & DRM_BRIDGE_OP_MODES) { 688 - drm_bridge_put(bridge_modes); 689 - bridge_modes = drm_bridge_get(bridge); 690 - } 701 + if (bridge->ops & DRM_BRIDGE_OP_EDID) 702 + bridge_connector->bridge_edid = bridge; 703 + if (bridge->ops & DRM_BRIDGE_OP_HPD) 704 + bridge_connector->bridge_hpd = bridge; 705 + if (bridge->ops & DRM_BRIDGE_OP_DETECT) 706 + bridge_connector->bridge_detect = bridge; 707 + if (bridge->ops & DRM_BRIDGE_OP_MODES) 708 + bridge_connector->bridge_modes = bridge; 691 709 if (bridge->ops & DRM_BRIDGE_OP_HDMI) { 692 - if (bridge_hdmi) 710 + if (bridge_connector->bridge_hdmi) 693 711 return ERR_PTR(-EBUSY); 694 712 if (!bridge->funcs->hdmi_write_infoframe || 695 713 !bridge->funcs->hdmi_clear_infoframe) 696 714 return ERR_PTR(-EINVAL); 697 715 698 - bridge_hdmi = drm_bridge_get(bridge); 716 + bridge_connector->bridge_hdmi = bridge; 699 717 700 718 if (bridge->supported_formats) 701 719 supported_formats = bridge->supported_formats; ··· 696 730 } 697 731 698 732 if (bridge->ops & DRM_BRIDGE_OP_HDMI_AUDIO) { 699 - if (bridge_hdmi_audio) 733 + if (bridge_connector->bridge_hdmi_audio) 700 734 return ERR_PTR(-EBUSY); 701 735 702 - if (bridge_dp_audio) 736 + if (bridge_connector->bridge_dp_audio) 703 737 return ERR_PTR(-EBUSY); 704 738 705 739 if (!bridge->hdmi_audio_max_i2s_playback_channels && ··· 710 744 !bridge->funcs->hdmi_audio_shutdown) 711 745 return ERR_PTR(-EINVAL); 712 746 713 - bridge_hdmi_audio = drm_bridge_get(bridge); 747 + bridge_connector->bridge_hdmi_audio = bridge; 714 748 } 715 749 716 750 if (bridge->ops & DRM_BRIDGE_OP_DP_AUDIO) { 717 - if (bridge_dp_audio) 751 + if (bridge_connector->bridge_dp_audio) 718 752 return ERR_PTR(-EBUSY); 719 753 720 - if (bridge_hdmi_audio) 754 + if (bridge_connector->bridge_hdmi_audio) 721 755 return ERR_PTR(-EBUSY); 722 756 723 757 if (!bridge->hdmi_audio_max_i2s_playback_channels && ··· 728 762 !bridge->funcs->dp_audio_shutdown) 729 763 return ERR_PTR(-EINVAL); 730 764 731 - bridge_dp_audio = drm_bridge_get(bridge); 765 + bridge_connector->bridge_dp_audio = bridge; 732 766 } 733 767 734 768 if (bridge->ops & DRM_BRIDGE_OP_HDMI_CEC_NOTIFIER) { ··· 739 773 } 740 774 741 775 if (bridge->ops & DRM_BRIDGE_OP_HDMI_CEC_ADAPTER) { 742 - if (bridge_hdmi_cec) 776 + if (bridge_connector->bridge_hdmi_cec) 743 777 return ERR_PTR(-EBUSY); 744 778 745 - bridge_hdmi_cec = drm_bridge_get(bridge); 779 + bridge_connector->bridge_hdmi_cec = bridge; 746 780 747 781 if (!bridge->funcs->hdmi_cec_enable || 748 782 !bridge->funcs->hdmi_cec_log_addr || ··· 762 796 ddc = bridge->ddc; 763 797 764 798 if (drm_bridge_is_panel(bridge)) 765 - panel_bridge = drm_bridge_get(bridge); 799 + panel_bridge = bridge; 766 800 767 801 if (bridge->support_hdcp) 768 802 support_hdcp = true; ··· 771 805 if (connector_type == DRM_MODE_CONNECTOR_Unknown) 772 806 return ERR_PTR(-EINVAL); 773 807 774 - if (bridge_hdmi) { 808 + if (bridge_connector->bridge_hdmi) { 775 809 if (!connector->ycbcr_420_allowed) 776 810 supported_formats &= ~BIT(HDMI_COLORSPACE_YUV420); 777 811 778 812 ret = drmm_connector_hdmi_init(drm, connector, 779 - bridge_hdmi->vendor, 780 - bridge_hdmi->product, 813 + bridge_connector->bridge_hdmi->vendor, 814 + bridge_connector->bridge_hdmi->product, 781 815 &drm_bridge_connector_funcs, 782 816 &drm_bridge_connector_hdmi_funcs, 783 817 connector_type, ddc, ··· 793 827 return ERR_PTR(ret); 794 828 } 795 829 796 - if (bridge_hdmi_audio || bridge_dp_audio) { 830 + if (bridge_connector->bridge_hdmi_audio || 831 + bridge_connector->bridge_dp_audio) { 797 832 struct device *dev; 798 833 struct drm_bridge *bridge; 799 834 800 - if (bridge_hdmi_audio) 801 - bridge = bridge_hdmi_audio; 835 + if (bridge_connector->bridge_hdmi_audio) 836 + bridge = bridge_connector->bridge_hdmi_audio; 802 837 else 803 - bridge = bridge_dp_audio; 838 + bridge = bridge_connector->bridge_dp_audio; 804 839 805 840 dev = bridge->hdmi_audio_dev; 806 841 ··· 815 848 return ERR_PTR(ret); 816 849 } 817 850 818 - if (bridge_hdmi_cec && 819 - bridge_hdmi_cec->ops & DRM_BRIDGE_OP_HDMI_CEC_NOTIFIER) { 820 - struct drm_bridge *bridge = bridge_hdmi_cec; 851 + if (bridge_connector->bridge_hdmi_cec && 852 + bridge_connector->bridge_hdmi_cec->ops & DRM_BRIDGE_OP_HDMI_CEC_NOTIFIER) { 853 + struct drm_bridge *bridge = bridge_connector->bridge_hdmi_cec; 821 854 822 855 ret = drmm_connector_hdmi_cec_notifier_register(connector, 823 856 NULL, ··· 826 859 return ERR_PTR(ret); 827 860 } 828 861 829 - if (bridge_hdmi_cec && 830 - bridge_hdmi_cec->ops & DRM_BRIDGE_OP_HDMI_CEC_ADAPTER) { 831 - struct drm_bridge *bridge = bridge_hdmi_cec; 862 + if (bridge_connector->bridge_hdmi_cec && 863 + bridge_connector->bridge_hdmi_cec->ops & DRM_BRIDGE_OP_HDMI_CEC_ADAPTER) { 864 + struct drm_bridge *bridge = bridge_connector->bridge_hdmi_cec; 832 865 833 866 ret = drmm_connector_hdmi_cec_register(connector, 834 867 &drm_bridge_connector_hdmi_cec_funcs, ··· 841 874 842 875 drm_connector_helper_add(connector, &drm_bridge_connector_helper_funcs); 843 876 844 - if (bridge_hpd) 877 + if (bridge_connector->bridge_hpd) 845 878 connector->polled = DRM_CONNECTOR_POLL_HPD; 846 - else if (bridge_detect) 879 + else if (bridge_connector->bridge_detect) 847 880 connector->polled = DRM_CONNECTOR_POLL_CONNECT 848 881 | DRM_CONNECTOR_POLL_DISCONNECT; 849 882 ··· 853 886 if (support_hdcp && IS_REACHABLE(CONFIG_DRM_DISPLAY_HELPER) && 854 887 IS_ENABLED(CONFIG_DRM_DISPLAY_HDCP_HELPER)) 855 888 drm_connector_attach_content_protection_property(connector, true); 856 - 857 - bridge_connector->bridge_edid = drm_bridge_get(bridge_edid); 858 - bridge_connector->bridge_hpd = drm_bridge_get(bridge_hpd); 859 - bridge_connector->bridge_detect = drm_bridge_get(bridge_detect); 860 - bridge_connector->bridge_modes = drm_bridge_get(bridge_modes); 861 - bridge_connector->bridge_hdmi = drm_bridge_get(bridge_hdmi); 862 - bridge_connector->bridge_hdmi_audio = drm_bridge_get(bridge_hdmi_audio); 863 - bridge_connector->bridge_dp_audio = drm_bridge_get(bridge_dp_audio); 864 - bridge_connector->bridge_hdmi_cec = drm_bridge_get(bridge_hdmi_cec); 865 889 866 890 return connector; 867 891 }