<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<div class="moz-cite-prefix">On 5/20/22 16:41, Daniel Dadap wrote:<br>
</div>
<blockquote type="cite" cite="mid:80fa1ee5-6204-6178-e7e2-ac98038cd8d8@nvidia.com">
<br>
On 5/17/22 10:23, Hans de Goede wrote:
<br>
<blockquote type="cite">On x86/ACPI boards the acpi_video driver
will usually initializing before
<br>
the kms driver (except i915). This causes
/sys/class/backlight/acpi_video0
<br>
to show up and then the kms driver registers its own native
backlight
<br>
device after which the drivers/acpi/video_detect.c code
unregisters
<br>
the acpi_video0 device (when
acpi_video_get_backlight_type()==native).
<br>
<br>
This means that userspace briefly sees 2 devices and the
disappearing of
<br>
acpi_video0 after a brief time confuses the systemd backlight
level
<br>
save/restore code, see e.g.:
<br>
<a class="moz-txt-link-freetext" href="https://bbs.archlinux.org/viewtopic.php?id=269920">https://bbs.archlinux.org/viewtopic.php?id=269920</a>
<br>
<br>
To fix this make backlight class device registration a separate
step
<br>
done by a new acpi_video_register_backlight() function. The
intend is for
<br>
this to be called by the drm/kms driver *after* it is done
setting up its
<br>
own native backlight device. So that
acpi_video_get_backlight_type() knows
<br>
if a native backlight will be available or not at acpi_video
backlight
<br>
registration time, avoiding the add + remove dance.
<br>
</blockquote>
<br>
<br>
If I'm understanding this correctly, it seems we will want to call
acpi_video_register_backlight() from the NVIDIA proprietary driver
in a fallback path in case the driver's own GPU-controlled
backlight handler either should not be used, or fails to register.
That sounds reasonable enough, but I'm not sure what should be
done about drivers like nvidia-wmi-ec-backlight, which are
independent of the GPU hardware, and wouldn't be part of the
acpi_video driver, either. There are a number of other similar
vendor-y/platform-y type backlight drivers in
drivers/video/backlight and drivers/platform/x86 that I think
would be in a similar situation.
<br>
<br>
From a quick skim of the ACPI video driver, it seems that perhaps
nvidia-wmi-ec-backlight is missing a call to
acpi_video_set_dmi_backlight_type(), perhaps with the
acpi_backlight_vendor value? But I'm not familiar enough with this
code to be sure that nobody will be checking
acpi_video_get_backlight_type() before nvidia-wmi-ec-backlight
loads. I'll take a closer look to try to convince myself that it
makes sense.
<br>
<br>
<br>
<blockquote type="cite">Note the new
acpi_video_register_backlight() function is also called from
<br>
a delayed work to ensure that the acpi_video backlight devices
does get
<br>
registered if necessary even if there is no drm/kms driver or
when it is
<br>
disabled.
<br>
</blockquote>
<br>
<br>
It sounds like maybe everything should be fine as long as
nvidia-wmi-ec-backlight (and other vendor-y/platform-y type
drivers) gets everything set up before the delayed work which
calls acpi_video_register_backlight()? But then is it really
necessary to explicitly call acpi_video_register_backlight() from
the DRM drivers if it's going to be called later if no GPU driver
registered a backlight handler, anyway? Then we'd just need to
make sure that the iGPU and dGPU drivers won't attempt to register
a backlight handler on systems where a vendor-y/platform-y driver
is supposed to handle the backlight instead, which sounds like it
has the potential to be quite messy.
<br>
<br>
</blockquote>
<p><br>
</p>
<p>Ah, I see you addressed this concern in your RFC (sorry for
missing that, earlier):<br>
<br>
</p>
<p>
<blockquote type="cite">
<pre id="b">The above only takes native vs acpi_video backlight issues into
account, there are also a couple of other scenarios which may
lead to multiple backlight-devices getting registered:
1) Apple laptops using the apple_gmux driver
2) Nvidia laptops using the (new) nvidia-wmi-ec-backlight driver
3) drivers/platform/x86 drivers calling acpi_video_set_dmi_backlight_type()
to override the normal acpi_video_get_backlight_type() heuristics after
the native/acpi_video drivers have already loaded
The plan for 1) + 2) is to extend the acpi_backlight_type enum with
acpi_backlight_gmux and acpi_backlight_nvidia_wmi_ec values and to add
detection of these 2 to acpi_video_get_backlight_type().</pre>
</blockquote>
<br>
Is there a reason these shouldn't have the same, generic, type,
rather than separate, driver-specific ones? I don't foresee any
situation where a system would need to use these two particular
drivers simultaneously. Multiple DRM drivers can coexist on the
same system, and even though the goal here is to remove the
existing "multiple backlight interfaces for the same panel"
situation, there shouldn't be any reason why more than one DRM
driver couldn't register backlight handlers at the same time, so
long as they are driving distinct panels. If we don't need
separate backlight types for individual DRM drivers, why should we
have them for apple_gmux and nvidia_wmi_ec_backlight?<br>
<br>
I still think that relying on the GPU drivers to correctly know
whether they should register their backlight handlers when a
platform-level device is supposed to register one instead might be
easier said than done, especially on systems where the same panel
could potentially be driven by more than one GPU (but not at the
same time).<br>
<br>
</p>
<blockquote type="cite" cite="mid:80fa1ee5-6204-6178-e7e2-ac98038cd8d8@nvidia.com">Recall
that on at least one system, both amdgpu and the NVIDIA
proprietary driver registered a handler even when it shouldn't:
<a class="moz-txt-link-freetext" href="https://patchwork.kernel.org/project/platform-driver-x86/patch/20220316203325.2242536-1-ddadap@nvidia.com/">https://patchwork.kernel.org/project/platform-driver-x86/patch/20220316203325.2242536-1-ddadap@nvidia.com/</a>
- I didn't have direct access to this system, but the fact that
the NVIDIA driver registered a handler was almost certainly a bug
in either the driver or the system's firmware (on other systems
with the same type of backlight hardware, NVIDIA does not register
a handler), and I imagine the same is true of the amdgpu driver.
In all likelihood nouveau would have probably tried to register
one too; I am not certain whether the person who reported the
issue to me had tested with nouveau. I'm not convinced that the
GPU drivers can reliably determine whether or not they are
supposed to register, but maybe cases where they aren't, such as
the system mentioned above, are supposed to be handled in a quirks
table somewhere.
<br>
<br>
<br>
<blockquote type="cite">Signed-off-by: Hans de Goede
<a class="moz-txt-link-rfc2396E" href="mailto:hdegoede@redhat.com"><hdegoede@redhat.com></a>
<br>
---
<br>
drivers/acpi/acpi_video.c | 45
++++++++++++++++++++++++++++++++++++---
<br>
include/acpi/video.h | 2 ++
<br>
2 files changed, 44 insertions(+), 3 deletions(-)
<br>
<br>
diff --git a/drivers/acpi/acpi_video.c
b/drivers/acpi/acpi_video.c
<br>
index 95d4868f6a8c..79e75dc86243 100644
<br>
--- a/drivers/acpi/acpi_video.c
<br>
+++ b/drivers/acpi/acpi_video.c
<br>
@@ -31,6 +31,12 @@
<br>
#define ACPI_VIDEO_BUS_NAME "Video Bus"
<br>
#define ACPI_VIDEO_DEVICE_NAME "Video Device"
<br>
+/*
<br>
+ * Display probing is known to take up to 5 seconds, so delay
the fallback
<br>
+ * backlight registration by 5 seconds + 3 seconds for some
extra margin.
<br>
+ */
<br>
+#define ACPI_VIDEO_REGISTER_BACKLIGHT_DELAY (8 * HZ)
<br>
+
<br>
#define MAX_NAME_LEN 20
<br>
MODULE_AUTHOR("Bruno Ducrot");
<br>
@@ -80,6 +86,9 @@ static LIST_HEAD(video_bus_head);
<br>
static int acpi_video_bus_add(struct acpi_device *device);
<br>
static int acpi_video_bus_remove(struct acpi_device *device);
<br>
static void acpi_video_bus_notify(struct acpi_device *device,
u32 event);
<br>
+static void acpi_video_bus_register_backlight_work(struct
work_struct *ignored);
<br>
+static DECLARE_DELAYED_WORK(video_bus_register_backlight_work,
<br>
+ acpi_video_bus_register_backlight_work);
<br>
void acpi_video_detect_exit(void);
<br>
/*
<br>
@@ -1862,8 +1871,6 @@ static int
acpi_video_bus_register_backlight(struct acpi_video_bus *video)
<br>
if (video->backlight_registered)
<br>
return 0;
<br>
- acpi_video_run_bcl_for_osi(video);
<br>
-
<br>
if (acpi_video_get_backlight_type(false) !=
acpi_backlight_video)
<br>
return 0;
<br>
@@ -2089,7 +2096,11 @@ static int acpi_video_bus_add(struct
acpi_device *device)
<br>
list_add_tail(&video->entry, &video_bus_head);
<br>
mutex_unlock(&video_list_lock);
<br>
- acpi_video_bus_register_backlight(video);
<br>
+ /*
<br>
+ * The userspace visible backlight_device gets registered
separately
<br>
+ * from acpi_video_register_backlight().
<br>
+ */
<br>
+ acpi_video_run_bcl_for_osi(video);
<br>
acpi_video_bus_add_notify_handler(video);
<br>
return 0;
<br>
@@ -2128,6 +2139,11 @@ static int acpi_video_bus_remove(struct
acpi_device *device)
<br>
return 0;
<br>
}
<br>
+static void acpi_video_bus_register_backlight_work(struct
work_struct *ignored)
<br>
+{
<br>
+ acpi_video_register_backlight();
<br>
+}
<br>
+
<br>
static int __init is_i740(struct pci_dev *dev)
<br>
{
<br>
if (dev->device == 0x00D1)
<br>
@@ -2238,6 +2254,17 @@ int acpi_video_register(void)
<br>
*/
<br>
register_count = 1;
<br>
+ /*
<br>
+ * acpi_video_bus_add() skips registering the userspace
visible
<br>
+ * backlight_device. The intend is for this to be
registered by the
<br>
+ * drm/kms driver calling acpi_video_register_backlight()
*after* it is
<br>
+ * done setting up its own native backlight device. The
delayed work
<br>
+ * ensures that acpi_video_register_backlight() always gets
called
<br>
+ * eventually, in case there is no drm/kms driver or it is
disabled.
<br>
+ */
<br>
+
schedule_delayed_work(&video_bus_register_backlight_work,
<br>
+ ACPI_VIDEO_REGISTER_BACKLIGHT_DELAY);
<br>
+
<br>
leave:
<br>
mutex_unlock(®ister_count_mutex);
<br>
return ret;
<br>
@@ -2248,6 +2275,7 @@ void acpi_video_unregister(void)
<br>
{
<br>
mutex_lock(®ister_count_mutex);
<br>
if (register_count) {
<br>
+
cancel_delayed_work_sync(&video_bus_register_backlight_work);
<br>
acpi_bus_unregister_driver(&acpi_video_bus);
<br>
register_count = 0;
<br>
}
<br>
@@ -2255,6 +2283,17 @@ void acpi_video_unregister(void)
<br>
}
<br>
EXPORT_SYMBOL(acpi_video_unregister);
<br>
+void acpi_video_register_backlight(void)
<br>
+{
<br>
+ struct acpi_video_bus *video;
<br>
+
<br>
+ mutex_lock(&video_list_lock);
<br>
+ list_for_each_entry(video, &video_bus_head, entry)
<br>
+ acpi_video_bus_register_backlight(video);
<br>
+ mutex_unlock(&video_list_lock);
<br>
+}
<br>
+EXPORT_SYMBOL(acpi_video_register_backlight);
<br>
+
<br>
void acpi_video_unregister_backlight(void)
<br>
{
<br>
struct acpi_video_bus *video;
<br>
diff --git a/include/acpi/video.h b/include/acpi/video.h
<br>
index e31afb93379a..b2f7dc1f354a 100644
<br>
--- a/include/acpi/video.h
<br>
+++ b/include/acpi/video.h
<br>
@@ -53,6 +53,7 @@ enum acpi_backlight_type {
<br>
#if IS_ENABLED(CONFIG_ACPI_VIDEO)
<br>
extern int acpi_video_register(void);
<br>
extern void acpi_video_unregister(void);
<br>
+extern void acpi_video_register_backlight(void);
<br>
extern int acpi_video_get_edid(struct acpi_device *device, int
type,
<br>
int device_id, void **edid);
<br>
extern enum acpi_backlight_type
acpi_video_get_backlight_type(bool native);
<br>
@@ -68,6 +69,7 @@ extern int acpi_video_get_levels(struct
acpi_device *device,
<br>
#else
<br>
static inline int acpi_video_register(void) { return -ENODEV;
}
<br>
static inline void acpi_video_unregister(void) { return; }
<br>
+static inline void acpi_video_register_backlight(void) {
return; }
<br>
static inline int acpi_video_get_edid(struct acpi_device
*device, int type,
<br>
int device_id, void **edid)
<br>
{
<br>
</blockquote>
</blockquote>
</body>
</html>