lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <69f0c53a-0ac3-4858-a644-373af0473ddd@quicinc.com>
Date: Tue, 24 Jun 2025 17:56:56 +0800
From: Yongxing Mou <quic_yongmou@...cinc.com>
To: Dmitry Baryshkov <dmitry.baryshkov@....qualcomm.com>
CC: Rob Clark <robin.clark@....qualcomm.com>,
        Abhinav Kumar
	<abhinav.kumar@...ux.dev>,
        Jessica Zhang <jessica.zhang@....qualcomm.com>,
        Sean Paul <sean@...rly.run>,
        Marijn Suijten <marijn.suijten@...ainline.org>,
        David Airlie <airlied@...il.com>, Simona Vetter <simona@...ll.ch>,
        <linux-arm-msm@...r.kernel.org>, <dri-devel@...ts.freedesktop.org>,
        <freedreno@...ts.freedesktop.org>, <linux-kernel@...r.kernel.org>,
        "Abhinav
 Kumar" <quic_abhinavk@...cinc.com>
Subject: Re: [PATCH v2 29/38] drm/msm/dp: add connector abstraction for DP MST



On 2025/6/19 19:33, Dmitry Baryshkov wrote:
> [initially I responded off-list by mistake, sorry for the confusion and 
> possible duplicates]
> 
> On 19/06/2025 12:26, Yongxing Mou wrote:
>>
>>
>> On 2025/6/16 22:41, Dmitry Baryshkov wrote:
>>> On 16/06/2025 17:09, Yongxing Mou wrote:
>>>>
>>>>
>>>> On 2025/6/11 22:31, Dmitry Baryshkov wrote:
>>>>> On Wed, Jun 11, 2025 at 08:06:28PM +0800, Yongxing Mou wrote:
>>>>>>
>>>>>>
>>>>>> On 2025/6/9 23:44, Dmitry Baryshkov wrote:
>>>>>>> On Mon, Jun 09, 2025 at 08:21:48PM +0800, Yongxing Mou wrote:
>>>>>>>> From: Abhinav Kumar <quic_abhinavk@...cinc.com>
>>>>>>>>
>>>>>>>> Add connector abstraction for the DP MST. Each MST encoder
>>>>>>>> is connected through a DRM bridge to a MST connector and each
>>>>>>>> MST connector has a DP panel abstraction attached to it.
>>>>>>>>
>>>>>>>> Signed-off-by: Abhinav Kumar <quic_abhinavk@...cinc.com>
>>>>>>>> Signed-off-by: Yongxing Mou <quic_yongmou@...cinc.com>
>>>>>>>> ---
>>>>>>>>    drivers/gpu/drm/msm/dp/dp_mst_drm.c | 515 +++++++++++++++++++ 
>>>>>>>> + + + ++++++++++++++
>>>>>>>>    drivers/gpu/drm/msm/dp/dp_mst_drm.h |   3 +
>>>>>>>>    2 files changed, 518 insertions(+)
>>>>>>>
>>>>>>> It generally feels liks 80% of this patch is a generic code. Please
>>>>>>> extract generic DP MST connector and push it under drm/display. 
>>>>>>> Other DP
>>>>>>> MST drivers should be able to use it.
>>>>>>>
>>>>>>>>
>>>>>>>> diff --git a/drivers/gpu/drm/msm/dp/dp_mst_drm.c b/drivers/gpu/ 
>>>>>>>> drm/ msm/dp/dp_mst_drm.c
>>>>>>>> index 
>>>>>>>> a3ea34ae63511db0ac920cbeebe30c4e2320b8c4..489fa46aa518ff1cc5f4769b2153fc5153c4cb41 100644
>>>>>>>> --- a/drivers/gpu/drm/msm/dp/dp_mst_drm.c
>>>>>>>> +++ b/drivers/gpu/drm/msm/dp/dp_mst_drm.c
>>>>>>>> @@ -25,8 +25,12 @@
>>>>>>>>     * OF THIS SOFTWARE.
>>>>>>>>     */
>>>>>>>> +#include <drm/drm_edid.h>
>>>>>>>> +#include <drm/drm_managed.h>
>>>>>>>>    #include "dp_mst_drm.h"
>>>>>>>> +#define MAX_DPCD_TRANSACTION_BYTES 16
>>>>>>>> +
>>>>>>>>    static struct drm_private_state 
>>>>>>>> *msm_dp_mst_duplicate_bridge_state(struct drm_private_obj *obj)
>>>>>>>>    {
>>>>>>>>        struct msm_dp_mst_bridge_state *state;
>>>>>>>> @@ -79,6 +83,61 @@ static int msm_dp_mst_find_vcpi_slots(struct 
>>>>>>>> drm_dp_mst_topology_mgr *mgr, int p
>>>>>>>>        return num_slots;
>>>>>>>>    }
>>>>>>>> +static int msm_dp_mst_get_mst_pbn_div(struct msm_dp_panel 
>>>>>>>> *msm_dp_panel)
>>>>>>>> +{
>>>>>>>> +    struct msm_dp_link_info *link_info;
>>>>>>>> +
>>>>>>>> +    link_info = &msm_dp_panel->link_info;
>>>>>>>> +
>>>>>>>> +    return link_info->rate * link_info->num_lanes / 54000;
>>>>>>>> +}
>>>>>>>> +
>>>>>>>> +static int msm_dp_mst_compute_config(struct drm_atomic_state 
>>>>>>>> *state,
>>>>>>>> +                      struct msm_dp_mst *mst, struct 
>>>>>>>> drm_connector *connector,
>>>>>>>> +                      struct drm_display_mode *mode)
>>>>>>>> +{
>>>>>>>> +    int slots = 0, pbn;
>>>>>>>> +    struct msm_dp_mst_connector *mst_conn = 
>>>>>>>> to_msm_dp_mst_connector(connector);
>>>>>>>> +    int rc = 0;
>>>>>>>> +    struct drm_dp_mst_topology_state *mst_state;
>>>>>>>> +    int pbn_div;
>>>>>>>> +    struct msm_dp *dp_display = mst->msm_dp;
>>>>>>>> +    u32 bpp;
>>>>>>>> +
>>>>>>>> +    bpp = connector->display_info.bpc * 3;
>>>>>>>> +
>>>>>>>> +    pbn = drm_dp_calc_pbn_mode(mode->clock, bpp << 4);
>>>>>>>
>>>>>>> Is this going to change if DSC is in place? Will it bring 
>>>>>>> fractional BPP
>>>>>>> here?
>>>>>>>
>>>>>> Actually, in this patch series, MST not support DSC. So we just don't
>>>>>> consider this scenario.
>>>>>
>>>>> But you still can answer the question.
>>>>>
>>>>>
>>>>> [...]
>>>>>
>>>> 1.Emm, for my current understanding, if DSC is enabled, the BPP 
>>>> should change and recaculated.
>>>> Will it bring fractional BPP here?
>>>
>>> That's what I am asking
>>>
>>>>  >>>I'm not entirely sure about this answer. I checked how other 
>>>> drivers call this function, and they all use bpp << 4, so can we 
>>>> assume that this way of calling it is valid?
>>>
>>> It is valid. I'm trying to understand the implications and future 
>>> changes.
>>>
>>>>>>>> +
>>>>>>>> +    return msm_dp_display_mode_valid(dp_display, &dp_display- 
>>>>>>>> >connector->display_info, mode);
>>>>>>>> +}
>>>>>>>> +
>>>>>>>> +static struct drm_encoder *
>>>>>>>> +msm_dp_mst_atomic_best_encoder(struct drm_connector *connector, 
>>>>>>>> struct drm_atomic_state *state)
>>>>>>>
>>>>>>> Do we need this callback? Don't we have a fixed relationship between
>>>>>>> connectors and encoders?
>>>>>
>>>>> This was left unanswered.
>>>>>
>>>> Sorry, I didn't mean to skip any questions — I just planned to reply 
>>>> a bit later. Apologies for the confusion.
>>>> For this question, yes , we don't have the fixed relationship 
>>>> between them. Under the current codes, the Connector selects the 
>>>> available encoder and bridge in order from index 0 to 4 (up to 
>>>> max_streams) when the connector's status changes to 'connected'.
>>>
>>> Why? Can we have 1:1 relationship as we do with other bridges?
>>>
>> Emm, It may be because the number of MST connectors is not fixed, but 
>> rather determined by the number of output ports on the dongle. For 
>> example, in a 2-MST case, there are 2 encoders, but there could be 
>> four MST connectors if the dongle has four DP output ports. 
>> add_connector() creates MST connectors based on the number of outputs 
>> on the dongle, rather than the actual number of connected devices.
> 
> Ack, this should be a part of the commit message.
> 
>>>>>>>
>>>>>>>> +{
>>>>>>>> +    struct msm_dp_mst_connector *mst_conn = 
>>>>>>>> to_msm_dp_mst_connector(connector);
>>>>>>>> +    struct msm_dp *dp_display = mst_conn->msm_dp;
>>>>>>>> +    struct msm_dp_mst *mst = dp_display->msm_dp_mst;
>>>>>>>> +    struct drm_encoder *enc = NULL;
>>>>>>>> +    struct msm_dp_mst_bridge_state *bridge_state;
>>>>>>>> +    u32 i;
>>>>>>>> +    struct drm_connector_state *conn_state = 
>>>>>>>> drm_atomic_get_new_connector_state(state,
>>>>>>>> +                                            connector);
>>>>>>>> +
>>>>>>>
>>>>>
>>>>> [...]
>>>>>
>>>>>>>> +    if (drm_atomic_crtc_needs_modeset(crtc_state)) {
>>>>>>>> +        if (WARN_ON(!old_conn_state->best_encoder)) {
>>>>>>>> +            rc = -EINVAL;
>>>>>>>> +            goto end;
>>>>>>>> +        }
>>>>>>>> +
>>>>>>>> +        drm_bridge = 
>>>>>>>> drm_bridge_chain_get_first_bridge(old_conn_state->best_encoder);
>>>>>>>
>>>>>>> This really looks like this should be a bridge's callback.
>>>>>
>>>>> And this one
>>>>>
>>>> Emm, the bridge does not implement atomic_check(). All MST-related 
>>>> checks (such as drm_dp_atomic_release_time_slots, 
>>>> drm_dp_mst_atomic_check, or others) are performed in the connector's 
>>>> atomic_check function. I believe this is because both num_slots and 
>>>> pbn are stored in the bridge, and we call this to get the drm_bridge..
>>>
>>> So, please split them into connector and bridge checks, calling them 
>>> from corresponding hooks. It might be easier to migrate completely to 
>>> the bridge's atomic_check(). At least it will save us from this 
>>> clumsy code getting the bridge for the connector.
>>>
>> Maybe we don't need to move to bridge's atomic_check(). Connector's 
>> atomic_check() do 2 things: 1.Call drm_dp_atomic_release_time_slots 
>> when unplug, 2. Call drm_dp_atomic_find_time_slots and 
>> drm_dp_mst_atomic_check when plug in.
> 
> Actually... I don't think you are calling it in a correct way. It should 
> be called from the drm_mode_config.atomic_check, not from connector's 
> atomic_check(). See how nouveau driver does it. Even documentation 
> insists that it should be called _after_ checking the rest of the state.
> 
In the documentation, drm_dp_atomic_find_time_slots should be placed in 
drm_encoder_helper_funcs.atomic_check(), 
drm_dp_atomic_release_time_slots in 
&drm_connector_helper_funcs.atomic_check(), and drm_dp_mst_atomic_check 
in &drm_mode_config_funcs.atomic_check(). So maybe we can move these 
atomic_check() calls back to their original positions as do, as 
recommended in the documenttation.
>> 3 functions need drm_atomic_state, but it seems that 
>> drm_bridge_funcs.atomic_check() does not pass in drm_atomic_state. 
> 
> You can get drm_atomic_state from bridge_state->base.state, crtc_state- 
>  >state, connector_state->state, that's not really an issue.
> 
>> Actually both 2 actions only occur when need modeset. Maybe we can 
>> optimize this function in the following ways: (1) reduce unnecessary 
>> references to drm_bridge, especially since bridge_state-  >num_slots 
>> can replace with payload->time_slots; (2)As your comments, split the 
>> function into smaller parts to better reflect the logic.
> 
> Yes, please. Getting rid of bridge_state->num_slots is a good path forward.
> 
Emm, even if we can drop bridge_state->num_slots, we still need to 
access bridge_state when clearing bridge_state->connector and 
bridge_state->msm_dp_panel, so it might not be possible to completely 
eliminate the use of bridge_state here.
>>>
>>>>>>>
>>>>>>>> +        if (WARN_ON(!drm_bridge)) {
>>>>>>>> +            rc = -EINVAL;
>>>>>>>> +            goto end;
>>>>>>>> +        }
>>>>>>>> +        bridge = to_msm_dp_mst_bridge(drm_bridge);
>>>>>>>> +
>>>>>>>> +        bridge_state = msm_dp_mst_br_priv_state(state, bridge);
>>>>>>>> +        if (IS_ERR(bridge_state)) {
>>>>>>>> +            rc = PTR_ERR(bridge_state);
>>>>>>>> +            goto end;
>>>>>>>> +        }
>>>>>>>> +
>>>>>>>> +        if (WARN_ON(bridge_state->connector != connector)) {
>>>>>>>> +            rc = -EINVAL;
>>>>>>>> +            goto end;
>>>>>>>> +        }
>>>>>>>> +
>>>>>>>> +        slots = bridge_state->num_slots;
>>>>>>>> +        if (slots > 0) {
>>>>>>>> +            rc = drm_dp_atomic_release_time_slots(state,
>>>>>>>> +                                  &mst->mst_mgr,
>>>>>>>> +                                  mst_conn->mst_port);
>>>>>>>> +            if (rc) {
>>>>>>>> +                DRM_ERROR("failed releasing %d vcpi slots 
>>>>>>>> %d\n", slots, rc);
>>>>>>>> +                goto end;
>>>>>>>> +            }
>>>>>>>> +            vcpi_released = true;
>>>>>>>> +        }
>>>>>>>> +
>>>>>>>> +        if (!new_conn_state->crtc) {
>>>>>>>> +            /* for cases where crtc is not disabled the slots 
>>>>>>>> are not
>>>>>>>> +             * freed by drm_dp_atomic_release_time_slots. this 
>>>>>>>> results
>>>>>>>> +             * in subsequent atomic_check failing since 
>>>>>>>> internal slots
>>>>>>>> +             * were freed but not the dp mst mgr's
>>>>>>>> +             */
>>>>>>>> +            bridge_state->num_slots = 0;
>>>>>>>> +            bridge_state->connector = NULL;
>>>>>>>> +            bridge_state->msm_dp_panel = NULL;
>>>>>>>> +
>>>>>>>> +            drm_dbg_dp(dp_display->drm_dev, "clear best 
>>>>>>>> encoder: %d\n", bridge->id);
>>>>>>>> +        }
>>>>>>>> +    }
>>>>>>>
>>>>>>> This looks like there are several functions fused together. Please
>>>>>>> unfuse those into small and neat code blocks.
>>>>>
>>>>> And this :-D
>>>>>
>>>> Got it.. this code only do one thing, check and try to release 
>>>> time_slots.. we can try to package it into small functions..
>>>
>>> I still don't understand, why do we need to release time_slots here 
>>> instead of using MST helpers.
>>>
>> Emm , just as above reply.. when we need modeset, call 
>> drm_dp_atomic_release_time_slots to release payload and then clear 
>> bridge_state cached ..
> 
> I don't see other drivers limiting drm_dp_atomic_release_time_slots() to 
> the modeset case. Any reason for MSM driver to deviate from that?
> 
Actually, you are right. I think the drm_dp_atomic_release_time_slots 
function can handle the slots releases quite well by itself. This 
function can handle various changes in crtc_state quite well. These 
constraints are more about supporting the cleanup of 
bridge_state->connector and bridge_state->msm_dp_panel.
> 
> 
>>>>>>>
>>>>>>>> +
>>>>>>>> +mode_set:
>>>>>>>> +    if (!new_conn_state->crtc)
>>>>>>>> +        goto end;
>>>>>>>> +
>>>>>>>> +    crtc_state = drm_atomic_get_new_crtc_state(state, 
>>>>>>>> new_conn_state->crtc);
>>>>>>>> +
>>>>>>>> +    if (drm_atomic_crtc_needs_modeset(crtc_state) && 
>>>>>>>> crtc_state- >active) {
>>>>>>>
>>>>>>> Use of crtc_state->active doesn't look correct.
>>>>>
>>>>>
>>>>> ...
>>>>>
>>>> Sorry, I'm still not quite sure where the issue is. Could you please 
>>>> help point it out? Thanks~~
>>>
>>>
>>> Please refer to the documentation for drm_crtc_state::active. The 
>>> drivers are not supposed to use this field in checks.
>>>
>> Got it , so maybe drm_crtc_state::enable might more appropriate here..
> 
> Well, why do you need it in the first place? This will determine a 
> correct set of conditions.
> 
Got it. Let me look into whether this can be optimized.
> 
>>>>>>>
>>>>>>>> +        if (WARN_ON(!new_conn_state->best_encoder)) {
>>>>>>>> +            rc = -EINVAL;
>>>>>>>> +            goto end;
>>>>>>>> +        }
>>>>>>>> +
>>>>>>>> +        drm_bridge = 
>>>>>>>> drm_bridge_chain_get_first_bridge(new_conn_state->best_encoder);
>>>>>>>> +        if (WARN_ON(!drm_bridge)) {
>>>>>>>> +            rc = -EINVAL;
>>>>>>>> +            goto end;
>>>>>>>> +        }
>>>>>>>> +        bridge = to_msm_dp_mst_bridge(drm_bridge);
>>>>>>>> +
>>>>>>>> +        bridge_state = msm_dp_mst_br_priv_state(state, bridge);
>>>>>>>> +        if (IS_ERR(bridge_state)) {
>>>>>>>> +            rc = PTR_ERR(bridge_state);
>>>>>>>> +            goto end;
>>>>>>>> +        }
>>>>>>>> +
>>>>>>>> +        if (WARN_ON(bridge_state->connector != connector)) {
>>>>>>>> +            rc = -EINVAL;
>>>>>>>> +            goto end;
>>>>>>>> +        }
>>>>>>>
>>>>>>> Can all of this actually happen?
>>>>>
>>>>> ...
>>>>>
>>>> Actually not, I haven't encountered it yet. I'm not sure how to 
>>>> trigger it, but it might occur under race conditions? Or we just 
>>>> remove it untill some case it really happen..
>>>
>>> No. You actually think whether this condition can happen, then keep 
>>> it if it can (and drop it if it can not happen).
>>>
>> Got it. Let me test a few different cases to see if these scenarios 
>> occur.
> 
> No. It's not about testing. It's about asserting if the scenario can 
> occur or not per your call stacks and per the design / contract.
> 
Got it. Let me check this part again. I don't think these errors would 
occur under the current design. But if the system enters a  inconsistent 
error state, this code could help improve our stability.
> 


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ