[PATCH] drm/rockchip: cdn-dp: Remove redundant workarounds for firmware loading

Dragan Simic dsimic at manjaro.org
Tue Jul 9 09:26:20 PDT 2024


Hello Andy,

On 2024-07-09 12:46, Andy Yan wrote:
> At 2024-07-09 18:10:51, "Dragan Simic" <dsimic at manjaro.org> wrote:
>> On 2024-07-09 11:10, Andy Yan wrote:
>>> At 2024-07-09 16:17:06, "Dragan Simic" <dsimic at manjaro.org> wrote:
>>>> On 2024-07-08 09:46, Andy Yan wrote:
>>>>> At 2024-07-04 18:35:42, "Dragan Simic" <dsimic at manjaro.org> wrote:
>>>>>> On 2024-07-04 04:10, Andy Yan wrote:
>>>>>>> At 2024-07-04 07:32:02, "Dragan Simic" <dsimic at manjaro.org> 
>>>>>>> wrote:
>>>>>>>> After the additional firmware-related module information was
>>>>>>>> introduced by
>>>>>>>> the commit c0677e41a47f ("drm/rockchip: cdn-dp-core: add
>>>>>>>> MODULE_FIRMWARE
>>>>>>>> macro"), there's no longer need for the firmware-loading
>>>>>>>> workarounds
>>>>>>>> whose
>>>>>>>> sole purpose was to prevent the missing firmware blob in an
>>>>>>>> initial
>>>>>>>> ramdisk
>>>>>>>> from causing driver initialization to fail.  Thus, delete the
>>>>>>>> workarounds,
>>>>>>>> which removes a sizable chunk of redundant code.
>>>>>>> 
>>>>>>> What would happen if there was no ramdisk? And the firmware is in
>>>>>>> rootfs ?
>>>>>>> 
>>>>>>> For example: A buildroot based tiny embedded system。
>>>>>> 
>>>>>> Good point, let me explain, please.
>>>>>> 
>>>>>> In general, if a driver is built into the kernel, there should 
>>>>>> also
>>>>>> be
>>>>>> an initial ramdisk that contains the related firmware blobs, 
>>>>>> because
>>>>>> it's
>>>>>> unknown is the root filesystem available when the driver is 
>>>>>> probed.
>>>>>> If
>>>>>> a driver is built as a module and there's no initial ramdisk, 
>>>>>> having
>>>>>> the related firmware blobs on the root filesystem should be fine,
>>>>>> because
>>>>>> the firmware blobs and the kernel module become available at the
>>>>>> same
>>>>>> time, through the root filesystem. [1]
>>>>>> 
>>>>>> Another option for a driver built statically into the kernel, when
>>>>>> there's
>>>>>> no initial ramdisk, is to build the required firmware blobs into 
>>>>>> the
>>>>>> kernel
>>>>>> image. [2]  Of course, that's feasible only when a kernel image is
>>>>>> built
>>>>>> specificially for some device, because otherwise it would become 
>>>>>> too
>>>>>> large
>>>>>> because of too many drivers and their firmware blobs becoming
>>>>>> included,
>>>>>> but that seems to fit the Buildroot-based example.
>>>>>> 
>>>>>> To sum it up, mechanisms already exist in the kernel for various
>>>>>> scenarios
>>>>>> when it comes to loading firmware blobs.  Even if the deleted
>>>>>> workaround
>>>>>> attempts to solve some issue specific to some environment, that
>>>>>> isn't
>>>>>> the
>>>>>> right place or the right way for solving any issues of that kind.
>>>>>> 
>>>>>> While preparing this patch, I even tried to find another kernel
>>>>>> driver
>>>>>> that
>>>>>> also implements some similar workarounds for firmware loading, to
>>>>>> justify
>>>>>> the existence of such workarounds and to possibly move them into 
>>>>>> the
>>>>>> kernel's
>>>>>> firmware-loading interface.  Alas, I was unable to find such
>>>>>> workarounds
>>>>>> in
>>>>>> other drivers, which solidified my reasoning behind classifying 
>>>>>> the
>>>>>> removed
>>>>>> code as out-of-place and redundant.
>>>>> 
>>>>> For some tiny embedded system,there is no such ramdisk,for example:
>>>>> a buildroot based rootfs,the buildroot only generate rootfs。
>>>>> 
>>>>> And FYI, there are mainline drivers try to fix such issue by
>>>>> defer_probe,for example:
>>>>> smc_abc[0]
>>>>> There are also some other similar scenario in gpu driver{1}[2]
>>>>> 
>>>>> [0]https://elixir.bootlin.com/linux/latest/source/drivers/tee/optee/smc_abi.c#L1518
>>>>> [1]https://patchwork.kernel.org/project/dri-devel/patch/20240109120604.603700-1-javierm@redhat.com/
>>>>> [2]https://lore.kernel.org/dri-devel/87y1918psd.fsf@minerva.mail-host-address-is-not-set/T/
>>>> 
>>>> Thanks for providing these examples.
>>>> 
>>>> Before I continue thinking about the possible systemic solution,
>>>> could you please clarify the way Buildroot builds the kernel and
>>>> prepares the root filesystem?  I'm not familiar with Buildroot,
>>>> but it seems to me that it builds the drivers statically into the
>>>> produced kernel image, while it places the related firmware blobs
>>>> into the produced root filesystem.  Am I right there?
>>> 
>>> in practice we can chose build the drivers statically into the 
>>> kernel,
>>> we can also build it as a module。
>>> And in both case, the firmware blobs are put in rootfs。
>>> If the drivers is built as a module, the module will also put in
>>> rootfs,
>>> so its fine。
>>> But if a drivers is built into the kernel ,it maybe can't access the
>>> firmware blob
>>> before the rootfs is mounted.
>>> So we can see some drivers try to use  DEFER_PROBE to fix this issue.
>> 
>> When Buildroot builds the drivers statically into the kernel image,
>> can it also be told to build the required firmware blobs into the
>> kernel image, for which there's already support in the kernel?
> 
> I‘m not sure about that。Firmware and linux kernel are two seperate
> project or repository。
> And i’m also not sure if that needs the support of the specific driver
> to build the firmware into the kernel? >

Please see the link below, which I actually referred to.  That feature
should allow required firmware blobs to be built into the kernel image,
although I haven't tested it myself.

https://www.kernel.org/doc/Documentation/driver-api/firmware/built-in-fw.rst

>> Of course, that would be feasible if only a small number of firmware
>> blobs would end up built into the kernel image, i.e. if the Buildroot
>> build would be tailored for a specific board.
>> 
>> Otherwise...
>> 
>>>> As I already wrote earlier, and as the above-linked discussions
>>>> conclude, solving these issues doesn't belong to any specific 
>>>> driver.
>>>> It should be resolved within the kernel's firmware loading mechanism
>>>> instead, and no driver should be specific in that regard.
>>> 
>>> IT would be good if it can be resolved within the kernel's  firmware
>>> loading mechanism.
>> 
>> ... we'll need this as a systemic solution.
>> 
>>>>>> [1]
>>>>>> https://www.kernel.org/doc/Documentation/driver-api/firmware/direct-fs-lookup.rst
>>>>>> [2]
>>>>>> https://www.kernel.org/doc/Documentation/driver-api/firmware/built-in-fw.rst
>>>>>> 
>>>>>>>> Various utilities used by Linux distributions to generate 
>>>>>>>> initial
>>>>>>>> ramdisks
>>>>>>>> need to obey the firmware-related module information, so we can
>>>>>>>> rely
>>>>>>>> on the
>>>>>>>> firmware blob being present in the generated initial ramdisks.
>>>>>>>> 
>>>>>>>> Signed-off-by: Dragan Simic <dsimic at manjaro.org>
>>>>>>>> ---
>>>>>>>> drivers/gpu/drm/rockchip/cdn-dp-core.c | 53
>>>>>>>> +++++---------------------
>>>>>>>> 1 file changed, 10 insertions(+), 43 deletions(-)
>>>>>>>> 
>>>>>>>> diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c
>>>>>>>> b/drivers/gpu/drm/rockchip/cdn-dp-core.c
>>>>>>>> index bd7aa891b839..e1a7c6a1172b 100644
>>>>>>>> --- a/drivers/gpu/drm/rockchip/cdn-dp-core.c
>>>>>>>> +++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
>>>>>>>> @@ -44,9 +44,9 @@ static inline struct cdn_dp_device
>>>>>>>> *encoder_to_dp(struct drm_encoder *encoder)
>>>>>>>> #define DPTX_HPD_DEL		(2 << 12)
>>>>>>>> #define DPTX_HPD_SEL_MASK	(3 << 28)
>>>>>>>> 
>>>>>>>> -#define CDN_FW_TIMEOUT_MS	(64 * 1000)
>>>>>>>> #define CDN_DPCD_TIMEOUT_MS	5000
>>>>>>>> #define CDN_DP_FIRMWARE		"rockchip/dptx.bin"
>>>>>>>> +
>>>>>>>> MODULE_FIRMWARE(CDN_DP_FIRMWARE);
>>>>>>>> 
>>>>>>>> struct cdn_dp_data {
>>>>>>>> @@ -909,61 +909,28 @@ static int cdn_dp_audio_codec_init(struct
>>>>>>>> cdn_dp_device *dp,
>>>>>>>> 	return PTR_ERR_OR_ZERO(dp->audio_pdev);
>>>>>>>> }
>>>>>>>> 
>>>>>>>> -static int cdn_dp_request_firmware(struct cdn_dp_device *dp)
>>>>>>>> -{
>>>>>>>> -	int ret;
>>>>>>>> -	unsigned long timeout = jiffies +
>>>>>>>> msecs_to_jiffies(CDN_FW_TIMEOUT_MS);
>>>>>>>> -	unsigned long sleep = 1000;
>>>>>>>> -
>>>>>>>> -	WARN_ON(!mutex_is_locked(&dp->lock));
>>>>>>>> -
>>>>>>>> -	if (dp->fw_loaded)
>>>>>>>> -		return 0;
>>>>>>>> -
>>>>>>>> -	/* Drop the lock before getting the firmware to avoid blocking
>>>>>>>> boot
>>>>>>>> */
>>>>>>>> -	mutex_unlock(&dp->lock);
>>>>>>>> -
>>>>>>>> -	while (time_before(jiffies, timeout)) {
>>>>>>>> -		ret = request_firmware(&dp->fw, CDN_DP_FIRMWARE, dp->dev);
>>>>>>>> -		if (ret == -ENOENT) {
>>>>>>>> -			msleep(sleep);
>>>>>>>> -			sleep *= 2;
>>>>>>>> -			continue;
>>>>>>>> -		} else if (ret) {
>>>>>>>> -			DRM_DEV_ERROR(dp->dev,
>>>>>>>> -				      "failed to request firmware: %d\n", ret);
>>>>>>>> -			goto out;
>>>>>>>> -		}
>>>>>>>> -
>>>>>>>> -		dp->fw_loaded = true;
>>>>>>>> -		ret = 0;
>>>>>>>> -		goto out;
>>>>>>>> -	}
>>>>>>>> -
>>>>>>>> -	DRM_DEV_ERROR(dp->dev, "Timed out trying to load firmware\n");
>>>>>>>> -	ret = -ETIMEDOUT;
>>>>>>>> -out:
>>>>>>>> -	mutex_lock(&dp->lock);
>>>>>>>> -	return ret;
>>>>>>>> -}
>>>>>>>> -
>>>>>>>> static void cdn_dp_pd_event_work(struct work_struct *work)
>>>>>>>> {
>>>>>>>> 	struct cdn_dp_device *dp = container_of(work, struct
>>>>>>>> cdn_dp_device,
>>>>>>>> 						event_work);
>>>>>>>> 	struct drm_connector *connector = &dp->connector;
>>>>>>>> 	enum drm_connector_status old_status;
>>>>>>>> -
>>>>>>>> 	int ret;
>>>>>>>> 
>>>>>>>> 	mutex_lock(&dp->lock);
>>>>>>>> 
>>>>>>>> 	if (dp->suspended)
>>>>>>>> 		goto out;
>>>>>>>> 
>>>>>>>> -	ret = cdn_dp_request_firmware(dp);
>>>>>>>> -	if (ret)
>>>>>>>> -		goto out;
>>>>>>>> +	if (!dp->fw_loaded) {
>>>>>>>> +		ret = request_firmware(&dp->fw, CDN_DP_FIRMWARE, dp->dev);
>>>>>>>> +		if (ret) {
>>>>>>>> +			DRM_DEV_ERROR(dp->dev, "Loading firmware failed: %d\n", 
>>>>>>>> ret);
>>>>>>>> +			goto out;
>>>>>>>> +		}
>>>>>>>> +
>>>>>>>> +		dp->fw_loaded = true;
>>>>>>>> +	}
>>>>>>>> 
>>>>>>>> 	dp->connected = true;
>>>>>>>> 
>> 
>> _______________________________________________
>> Linux-rockchip mailing list
>> Linux-rockchip at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-rockchip



More information about the linux-arm-kernel mailing list