|
@@ -32,6 +32,7 @@
|
|
#include <linux/module.h>
|
|
#include <linux/module.h>
|
|
#include <linux/pci.h>
|
|
#include <linux/pci.h>
|
|
#include <linux/types.h>
|
|
#include <linux/types.h>
|
|
|
|
+#include <linux/workqueue.h>
|
|
#include <acpi/video.h>
|
|
#include <acpi/video.h>
|
|
|
|
|
|
ACPI_MODULE_NAME("video");
|
|
ACPI_MODULE_NAME("video");
|
|
@@ -41,6 +42,7 @@ void acpi_video_unregister_backlight(void);
|
|
|
|
|
|
static bool backlight_notifier_registered;
|
|
static bool backlight_notifier_registered;
|
|
static struct notifier_block backlight_nb;
|
|
static struct notifier_block backlight_nb;
|
|
|
|
+static struct work_struct backlight_notify_work;
|
|
|
|
|
|
static enum acpi_backlight_type acpi_backlight_cmdline = acpi_backlight_undef;
|
|
static enum acpi_backlight_type acpi_backlight_cmdline = acpi_backlight_undef;
|
|
static enum acpi_backlight_type acpi_backlight_dmi = acpi_backlight_undef;
|
|
static enum acpi_backlight_type acpi_backlight_dmi = acpi_backlight_undef;
|
|
@@ -262,6 +264,13 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
|
|
{ },
|
|
{ },
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+/* This uses a workqueue to avoid various locking ordering issues */
|
|
|
|
+static void acpi_video_backlight_notify_work(struct work_struct *work)
|
|
|
|
+{
|
|
|
|
+ if (acpi_video_get_backlight_type() != acpi_backlight_video)
|
|
|
|
+ acpi_video_unregister_backlight();
|
|
|
|
+}
|
|
|
|
+
|
|
static int acpi_video_backlight_notify(struct notifier_block *nb,
|
|
static int acpi_video_backlight_notify(struct notifier_block *nb,
|
|
unsigned long val, void *bd)
|
|
unsigned long val, void *bd)
|
|
{
|
|
{
|
|
@@ -269,9 +278,8 @@ static int acpi_video_backlight_notify(struct notifier_block *nb,
|
|
|
|
|
|
/* A raw bl registering may change video -> native */
|
|
/* A raw bl registering may change video -> native */
|
|
if (backlight->props.type == BACKLIGHT_RAW &&
|
|
if (backlight->props.type == BACKLIGHT_RAW &&
|
|
- val == BACKLIGHT_REGISTERED &&
|
|
|
|
- acpi_video_get_backlight_type() != acpi_backlight_video)
|
|
|
|
- acpi_video_unregister_backlight();
|
|
|
|
|
|
+ val == BACKLIGHT_REGISTERED)
|
|
|
|
+ schedule_work(&backlight_notify_work);
|
|
|
|
|
|
return NOTIFY_OK;
|
|
return NOTIFY_OK;
|
|
}
|
|
}
|
|
@@ -304,6 +312,8 @@ enum acpi_backlight_type acpi_video_get_backlight_type(void)
|
|
acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
|
|
acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
|
|
ACPI_UINT32_MAX, find_video, NULL,
|
|
ACPI_UINT32_MAX, find_video, NULL,
|
|
&video_caps, NULL);
|
|
&video_caps, NULL);
|
|
|
|
+ INIT_WORK(&backlight_notify_work,
|
|
|
|
+ acpi_video_backlight_notify_work);
|
|
backlight_nb.notifier_call = acpi_video_backlight_notify;
|
|
backlight_nb.notifier_call = acpi_video_backlight_notify;
|
|
backlight_nb.priority = 0;
|
|
backlight_nb.priority = 0;
|
|
if (backlight_register_notifier(&backlight_nb) == 0)
|
|
if (backlight_register_notifier(&backlight_nb) == 0)
|