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] [thread-next>] [day] [month] [year] [list]
Date:   Thu, 21 Jul 2022 14:36:32 +0300
From:   Dmitry Baryshkov <dmitry.baryshkov@...aro.org>
To:     Douglas Anderson <dianders@...omium.org>
Cc:     dri-devel@...ts.freedesktop.org, ville.syrjala@...ux.intel.com,
        sam@...nborg.org, robdclark@...il.com, linus.walleij@...aro.org,
        thierry.reding@...il.com, bjorn.andersson@...aro.org,
        Daniel Vetter <daniel@...ll.ch>,
        David Airlie <airlied@...ux.ie>,
        Sean Paul <seanpaul@...omium.org>, linux-kernel@...r.kernel.org
Subject: Re: [RFC PATCH 1/2] drm/panel-edp: Allow overriding the eDP EDID

On Thu, 21 Jul 2022 at 01:55, Douglas Anderson <dianders@...omium.org> wrote:
>
> I found that writing to `/sys/kernel/debug/dri/*/eDP*/edid_override`
> wasn't working for me. I could see the new EDID take effect in
> `/sys/class/drm/card*-eDP*/edid` but userspace wasn't seeing it..
>
> The problem was that panel-edp was caching the EDID that it read and
> using that over and over again.
>
> Let's change panel-edp to look at the EDID that's stored in the
> connector. This is still a cache, which is important since this
> function is called multiple times and readin the EDID is slow, but
> this property is automatically updated by drm_get_edid() (which reads
> the EDID) and also updated when writing the edid_override in debugfs.
>
> Fixes: 63358e24ee79 ("drm/panel: panel-simple: Cache the EDID as long as we retain power")
> Signed-off-by: Douglas Anderson <dianders@...omium.org>

A different proposal for you to consider:
Change drm_get_edid/drm_do_get_edid to return int rather than struct
edid, while caching the EDID in the connector. Or maybe add a new API
drm_read_edid() and make drm_get_edid() deprecated in favour of it.
The goal should be to let all drivers use connector-cached EDID rather
than getting  the EDID, parsing it and kfree()ing it immediately
afterwards.
Most probably we should be able to move
drm_connector_update_edid_property() into drm_do_get_edid() and drop
it from the rest of the code. This might require additional thought
about locking, to ensure that nobody pulls the cached edid out from
under our feet.

Extra "bonus" points to consider:
- Maybe it's time to add get_edid() to the drm_panel interface, teach
panel_bridge about it and let drm_bridge_connector handle all the
details?

So, while this looks like a longer path, I think it's worth checking
that we can refactor this piece of code.

> ---
>
>  drivers/gpu/drm/panel/panel-edp.c | 21 ++++++++++++---------
>  1 file changed, 12 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/gpu/drm/panel/panel-edp.c b/drivers/gpu/drm/panel/panel-edp.c
> index 3626469c4cc2..12241c1e32f7 100644
> --- a/drivers/gpu/drm/panel/panel-edp.c
> +++ b/drivers/gpu/drm/panel/panel-edp.c
> @@ -226,8 +226,6 @@ struct panel_edp {
>
>         const struct edp_panel_entry *detected_panel;
>
> -       struct edid *edid;
> -
>         struct drm_display_mode override_mode;
>
>         enum drm_panel_orientation orientation;
> @@ -580,11 +578,19 @@ static int panel_edp_get_modes(struct drm_panel *panel,
>         if (p->ddc) {
>                 pm_runtime_get_sync(panel->dev);
>
> -               if (!p->edid)
> -                       p->edid = drm_get_edid(connector, p->ddc);
> +               if (!connector->edid_blob_ptr) {
> +                       /*
> +                        * We read the EDID and then immediately free it,
> +                        * relying on the side effect of drm_get_edid() to store
> +                        * a copy in connector->edid_blob_ptr. We always use
> +                        * the copy cached in the connector since that allows
> +                        * the edid_override to work.
> +                        */
> +                       kfree(drm_get_edid(connector, p->ddc));
> +               }
>
> -               if (p->edid)
> -                       num += drm_add_edid_modes(connector, p->edid);
> +               if (connector->edid_blob_ptr)
> +                       num += drm_add_edid_modes(connector, connector->edid_blob_ptr->data);
>
>                 pm_runtime_mark_last_busy(panel->dev);
>                 pm_runtime_put_autosuspend(panel->dev);
> @@ -926,9 +932,6 @@ static int panel_edp_remove(struct device *dev)
>         if (panel->ddc && (!panel->aux || panel->ddc != &panel->aux->ddc))
>                 put_device(&panel->ddc->dev);
>
> -       kfree(panel->edid);
> -       panel->edid = NULL;
> -
>         return 0;
>  }
>
> --
> 2.37.0.170.g444d1eabd0-goog
>


--
With best wishes
Dmitry

Powered by blists - more mailing lists