Received: by 2002:a05:6359:c8b:b0:c7:702f:21d4 with SMTP id go11csp121293rwb; Thu, 6 Oct 2022 15:35:36 -0700 (PDT) X-Google-Smtp-Source: AMsMyM4nR6l0nYKMq4okGxrc3oF4IeTY6Ys/pnL34gxlsGD1bYOtdBogfTbBIDyriM00XZRL+GiK X-Received: by 2002:a17:907:2cf1:b0:77b:2dd9:7cc2 with SMTP id hz17-20020a1709072cf100b0077b2dd97cc2mr1736083ejc.121.1665095736579; Thu, 06 Oct 2022 15:35:36 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1665095736; cv=none; d=google.com; s=arc-20160816; b=omG7RZV2VwqU3LHACU3Wnuz88vJnBNHJzcJ6GOrIAKgjNxYJiRK8gm4qkHoWF/EOu1 8ahOYvHBbhmKARUIOY1/fDcQPUPhnwS1XkqB+QvwcGcOE4zdyBxLAb05sAsjmXcFRMFX Rl3QFIZUGEg1/L6NrVrJ3vqBHT7T2TYAKKNQEYbFvqpcHcyV5mza0FsuFO/1f0KdYzwC 4AXquIaFig760enoplXGyvlJJouOFdb9gjaWPN93fYEDzopIZIFLfWnbraVnCG+thrJ/ wzJRkL5cuSxA+WhyTQSvlGbOuJFAMWsmo0wiI22ubzmyscJirL0GlP9hE3gx6WynBTDC OpRg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:mime-version:message-id:date:references :organization:in-reply-to:subject:cc:to:from:dkim-signature; bh=EiXm8INkh//0aGWwDVxChOpJhrVSGIKJrOqAKk6x4MI=; b=rjvmEgowsfrOKz7k8r6DI7xsGhcwDhy1boo3y9bZJXf5hW72b1lClir+lRhIog7y56 5TZGZ8dovO7eap0B7bvqUwWYEs44TlbNasMB07zfhJYAOLZHtmDE8lgS7VbR/bwlEaRH jJBeIbACehkY7zdnj+JZHto25l28L4RQoM7YgZRQ78aIdJgdIh91DsbyynBVdJlDgg7/ BucZPYm6L1CbFzNFOvHVc815xE9V0mSOtLttJ4pKpyU0hblGM1y2s+Vw7FORvGuDpQgR FQSG5wV2YNr/jmJcoBU6R1ZJdfj64NgbNvbHPhIc9MqGch+uExFce43ommdjcxU4c+cg ejWQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=hNvEm46I; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id nd7-20020a170907628700b00781132a4ca6si655163ejc.850.2022.10.06.15.35.10; Thu, 06 Oct 2022 15:35:36 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=hNvEm46I; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232261AbiJFWXn (ORCPT + 99 others); Thu, 6 Oct 2022 18:23:43 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60436 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230526AbiJFWXl (ORCPT ); Thu, 6 Oct 2022 18:23:41 -0400 Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6F01FF1900 for ; Thu, 6 Oct 2022 15:23:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1665095020; x=1696631020; h=from:to:cc:subject:in-reply-to:references:date: message-id:mime-version; bh=lVLeFT7ehm0uqqM1feh9rSFqmEN5DFYhcLYRro+vBPE=; b=hNvEm46I2ZqykrMp3+iMAFaPNrtd6mst5/VeEDTLC4uc2YwFndx5/nzx 9W/k1sxOIEfmRFqgBXf7BIDd0rmS4mw+4tPkw2Q/P6ayGaNL2SdmJqy79 iNrQOy0+QqtwaIc4+65Tg2dhX1kuwYgb5EYN9VHePcJDtEQqSXjNZdDIf 7NZLebokjM4WDLC+/WyQrFKrNWLbunef+T2PLaMo5HgAcpO7HsIDs1KIG KAVhnmro6RRBZwKnUjDsutJ/MMdBEk0fvBYyENhG+oR+sw5wPH4FR70tE SkR7qTIUrZKSKD72PeYLlQL0So5nkDx/N4bRqbNj/eRTdmGg+yZanQm+s w==; X-IronPort-AV: E=McAfee;i="6500,9779,10492"; a="389881282" X-IronPort-AV: E=Sophos;i="5.95,164,1661842800"; d="scan'208";a="389881282" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Oct 2022 15:23:40 -0700 X-IronPort-AV: E=McAfee;i="6500,9779,10492"; a="767330999" X-IronPort-AV: E=Sophos;i="5.95,164,1661842800"; d="scan'208";a="767330999" Received: from ncercel-mobl1.ger.corp.intel.com (HELO localhost) ([10.252.60.239]) by fmsmga001-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Oct 2022 15:23:37 -0700 From: Jani Nikula To: Matthieu CHARETTE Cc: lkp@intel.com, kbuild-all@lists.01.org, tzimmermann@suse.de, airlied@linux.ie, linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, andrealmeid@igalia.com Subject: Re: [PATCH] drm: Fix EDID firmware load on resume In-Reply-To: <2YU3IR.4394CFYXZPEZ1@gmail.com> Organization: Intel Finland Oy - BIC 0357606-4 - Westendinkatu 7, 02160 Espoo References: <202207172035.mtErdlaw-lkp@intel.com> <20220727074152.43059-1-matthieu.charette@gmail.com> <87wnbqen2f.fsf@intel.com> <87edxqodq2.fsf@intel.com> <2YU3IR.4394CFYXZPEZ1@gmail.com> Date: Fri, 07 Oct 2022 01:23:37 +0300 Message-ID: <87fsg0pp5i.fsf@intel.com> MIME-Version: 1.0 Content-Type: text/plain X-Spam-Status: No, score=-4.3 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_EF,RCVD_IN_DNSWL_MED,SPF_HELO_NONE, SPF_NONE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Mon, 12 Sep 2022, Matthieu CHARETTE wrote: > Hi, > > Sorry for late reply. > > How do you propose to go then? > Can we still use a persistent platform device to load the firmware and > cache it? But, in this case the system will still crash in case the > user change drm.edid_firmware then, without replugging the device, he > suspends and resumes the machine. > Or you may have a better idea? Maybe. Please try [1]. Could it be as simple as that? BR, Jani. [1] https://patchwork.freedesktop.org/patch/msgid/20221006222146.2375217-1-jani.nikula@intel.com > > Thanks, > Matthieu > > On Mon, Aug 8 2022 at 08:19:01 PM +0300, Jani Nikula > wrote: >> On Mon, 08 Aug 2022, Matthieu CHARETTE >> wrote: >>> Sorry, What do you mean? >> >> You cache with one name at connector init time, but the name specified >> using drm.edid_firmware may be changed whenever, to cause the next >> EDID >> read to use a different EDID firmware. >> >> BR, >> Jani. >> >> >>> >>> Matthieu >>> >>> On Tue, Aug 2 2022 at 05:29:12 PM +0300, Jani Nikula >>> wrote: >>>> On Wed, 27 Jul 2022, Matthieu CHARETTE >>> > wrote: >>>>> Loading an EDID using drm.edid_firmware parameter makes resume to >>>>> fail >>>>> after firmware cache is being cleaned. This is because >>>>> edid_load() >>>>> use a >>>>> temporary device to request the firmware. This cause the EDID >>>>> firmware >>>>> not to be cached from suspend. And, requesting the EDID firmware >>>>> return >>>>> an error during resume. >>>>> So the request_firmware() call should use a permanent device for >>>>> each >>>>> connector. Also, we should cache the EDID even if no monitor is >>>>> connected, in case it's plugged while suspended. >>>> >>>> AFAICT this breaks changing drm.edid_firmware runtime. >>>> >>>> BR, >>>> Jani. >>>> >>>>> >>>>> Link: >>>>> Signed-off-by: Matthieu CHARETTE >>>> > >>>>> --- >>>>> drivers/gpu/drm/drm_connector.c | 9 ++++ >>>>> drivers/gpu/drm/drm_edid_load.c | 81 >>>>> ++++++++++++++++++++++++++++----- >>>>> include/drm/drm_connector.h | 12 +++++ >>>>> include/drm/drm_edid.h | 3 ++ >>>>> 4 files changed, 94 insertions(+), 11 deletions(-) >>>>> >>>>> diff --git a/drivers/gpu/drm/drm_connector.c >>>>> b/drivers/gpu/drm/drm_connector.c >>>>> index 1c48d162c77e..e8819ebf1c4b 100644 >>>>> --- a/drivers/gpu/drm/drm_connector.c >>>>> +++ b/drivers/gpu/drm/drm_connector.c >>>>> @@ -31,6 +31,7 @@ >>>>> #include >>>>> #include >>>>> >>>>> +#include >>>>> #include >>>>> >>>>> #include "drm_crtc_internal.h" >>>>> @@ -289,6 +290,9 @@ int drm_connector_init(struct drm_device >>>>> *dev, >>>>> >>>>> drm_connector_get_cmdline_mode(connector); >>>>> >>>>> + connector->edid_load_pdev = NULL; >>>>> + drm_cache_edid_firmware(connector); >>>>> + >>>>> /* We should add connectors at the end to avoid upsetting the >>>>> connector >>>>> * index too much. >>>>> */ >>>>> @@ -473,6 +477,11 @@ void drm_connector_cleanup(struct >>>>> drm_connector *connector) >>>>> connector->tile_group = NULL; >>>>> } >>>>> >>>>> + if (connector->edid_load_pdev) { >>>>> + platform_device_unregister(connector->edid_load_pdev); >>>>> + connector->edid_load_pdev = NULL; >>>>> + } >>>>> + >>>>> list_for_each_entry_safe(mode, t, &connector->probed_modes, >>>>> head) >>>>> drm_mode_remove(connector, mode); >>>>> >>>>> diff --git a/drivers/gpu/drm/drm_edid_load.c >>>>> b/drivers/gpu/drm/drm_edid_load.c >>>>> index 37d8ba3ddb46..5a82be9917ec 100644 >>>>> --- a/drivers/gpu/drm/drm_edid_load.c >>>>> +++ b/drivers/gpu/drm/drm_edid_load.c >>>>> @@ -167,6 +167,19 @@ static int edid_size(const u8 *edid, int >>>>> data_size) >>>>> return (edid[0x7e] + 1) * EDID_LENGTH; >>>>> } >>>>> >>>>> +static struct platform_device *edid_pdev(const char >>>>> *connector_name) >>>>> +{ >>>>> + struct platform_device *pdev = >>>>> platform_device_register_simple(connector_name, -1, NULL, 0); >>>>> + >>>>> + if (IS_ERR(pdev)) { >>>>> + DRM_ERROR("Failed to register EDID firmware platform device " >>>>> + "for connector \"%s\"\n", connector_name); >>>>> + return ERR_CAST(pdev); >>>>> + } >>>>> + >>>>> + return pdev; >>>>> +} >>>>> + >>>>> static void *edid_load(struct drm_connector *connector, const >>>>> char >>>>> *name, >>>>> const char *connector_name) >>>>> { >>>>> @@ -182,18 +195,17 @@ static void *edid_load(struct drm_connector >>>>> *connector, const char *name, >>>>> fwdata = generic_edid[builtin]; >>>>> fwsize = sizeof(generic_edid[builtin]); >>>>> } else { >>>>> - struct platform_device *pdev; >>>>> + struct platform_device *pdev = connector->edid_load_pdev; >>>>> int err; >>>>> >>>>> - pdev = platform_device_register_simple(connector_name, -1, >>>>> NULL, >>>>> 0); >>>>> - if (IS_ERR(pdev)) { >>>>> - DRM_ERROR("Failed to register EDID firmware platform device " >>>>> - "for connector \"%s\"\n", connector_name); >>>>> - return ERR_CAST(pdev); >>>>> + if (WARN_ON(!pdev)) { >>>>> + pdev = edid_pdev(connector_name); >>>>> + if (IS_ERR(pdev)) >>>>> + return ERR_CAST(pdev); >>>>> + connector->edid_load_pdev = pdev; >>>>> } >>>>> >>>>> err = request_firmware(&fw, name, &pdev->dev); >>>>> - platform_device_unregister(pdev); >>>>> if (err) { >>>>> DRM_ERROR("Requesting EDID firmware \"%s\" failed >>>>> (err=%d)\n", >>>>> name, err); >>>>> @@ -263,11 +275,9 @@ static void *edid_load(struct drm_connector >>>>> *connector, const char *name, >>>>> return edid; >>>>> } >>>>> >>>>> -struct edid *drm_load_edid_firmware(struct drm_connector >>>>> *connector) >>>>> +static char *edid_name(const char *connector_name) >>>>> { >>>>> - const char *connector_name = connector->name; >>>>> char *edidname, *last, *colon, *fwstr, *edidstr, *fallback = >>>>> NULL; >>>>> - struct edid *edid; >>>>> >>>>> if (edid_firmware[0] == '\0') >>>>> return ERR_PTR(-ENOENT); >>>>> @@ -310,8 +320,57 @@ struct edid *drm_load_edid_firmware(struct >>>>> drm_connector *connector) >>>>> if (*last == '\n') >>>>> *last = '\0'; >>>>> >>>>> - edid = edid_load(connector, edidname, connector_name); >>>>> + edidname = kstrdup(edidname, GFP_KERNEL); >>>>> + if (!edidname) { >>>>> + kfree(fwstr); >>>>> + return ERR_PTR(-ENOMEM); >>>>> + } >>>>> + >>>>> kfree(fwstr); >>>>> + return edidname; >>>>> +} >>>>> + >>>>> +void drm_cache_edid_firmware(struct drm_connector *connector) >>>>> +{ >>>>> + const char *connector_name = connector->name; >>>>> + const char *edidname = edid_name(connector_name); >>>>> + struct platform_device *pdev; >>>>> + int err; >>>>> + >>>>> + if (IS_ERR(edidname)) >>>>> + return; >>>>> + >>>>> + if (match_string(generic_edid_name, GENERIC_EDIDS, edidname) >= >>>>> 0) { >>>>> + kfree(edidname); >>>>> + return; >>>>> + } >>>>> + >>>>> + pdev = edid_pdev(connector_name); >>>>> + if (IS_ERR(pdev)) { >>>>> + kfree(edidname); >>>>> + return; >>>>> + } >>>>> + connector->edid_load_pdev = pdev; >>>>> + >>>>> + err = firmware_request_cache(&pdev->dev, edidname); >>>>> + if (err) >>>>> + DRM_ERROR("Requesting EDID firmware cache \"%s\" failed >>>>> (err=%d)\n", >>>>> + edidname, err); >>>>> + >>>>> + kfree(edidname); >>>>> +} >>>>> + >>>>> +struct edid *drm_load_edid_firmware(struct drm_connector >>>>> *connector) >>>>> +{ >>>>> + const char *connector_name = connector->name; >>>>> + const char *edidname = edid_name(connector_name); >>>>> + struct edid *edid; >>>>> + >>>>> + if (IS_ERR(edidname)) >>>>> + return ERR_CAST(edidname); >>>>> + >>>>> + edid = edid_load(connector, edidname, connector_name); >>>>> + kfree(edidname); >>>>> >>>>> return edid; >>>>> } >>>>> diff --git a/include/drm/drm_connector.h >>>>> b/include/drm/drm_connector.h >>>>> index 3ac4bf87f257..47c84741517e 100644 >>>>> --- a/include/drm/drm_connector.h >>>>> +++ b/include/drm/drm_connector.h >>>>> @@ -1573,6 +1573,18 @@ struct drm_connector { >>>>> */ >>>>> struct i2c_adapter *ddc; >>>>> >>>>> + /** >>>>> + * @edid_load_pdev: Platform device for loading EDID via >>>>> firmware. >>>>> + * >>>>> + * The platform device is registered in drm_connector_init() in >>>>> case a >>>>> + * custom EDID firmware is used with `edid_firmware` parameter. >>>>> Otherwise, >>>>> + * it is set to NULL. >>>>> + * >>>>> + * Platform device is unregistered in drm_connector_cleanup() >>>>> if >>>>> it >>>>> + * is not NULL. >>>>> + */ >>>>> + struct platform_device *edid_load_pdev; >>>>> + >>>>> /** >>>>> * @null_edid_counter: track sinks that give us all zeros for >>>>> the >>>>> EDID. >>>>> * Needed to workaround some HW bugs where we get all 0s >>>>> diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h >>>>> index b2756753370b..e907c928a35d 100644 >>>>> --- a/include/drm/drm_edid.h >>>>> +++ b/include/drm/drm_edid.h >>>>> @@ -378,10 +378,13 @@ int drm_av_sync_delay(struct drm_connector >>>>> *connector, >>>>> const struct drm_display_mode *mode); >>>>> >>>>> #ifdef CONFIG_DRM_LOAD_EDID_FIRMWARE >>>>> +void drm_cache_edid_firmware(struct drm_connector *connector); >>>>> struct edid *drm_load_edid_firmware(struct drm_connector >>>>> *connector); >>>>> int __drm_set_edid_firmware_path(const char *path); >>>>> int __drm_get_edid_firmware_path(char *buf, size_t bufsize); >>>>> #else >>>>> +inline void >>>>> +drm_cache_edid_firmware(struct drm_connector *connector); >>>>> static inline struct edid * >>>>> drm_load_edid_firmware(struct drm_connector *connector) >>>>> { >>>> >>>> -- >>>> Jani Nikula, Intel Open Source Graphics Center >>> >> >> -- >> Jani Nikula, Intel Open Source Graphics Center > > -- Jani Nikula, Intel Open Source Graphics Center