ACPI / button: Delay acpi_lid_initialize_state() until first user space open
ACPI _LID methods may depend on OpRegions and do not always handle handlers for those OpRegions not being present properly e.g. : Method (_LID, 0, NotSerialized) // _LID: Lid Status { If ((^^I2C5.PMI1.AVBL == One) && (^^GPO2.AVBL == One)) { Return (^^GPO2.LPOL) /* \_SB_.GPO2.LPOL */ } } Note the missing Return (1) when either of the OpRegions is not available, this causes (in this case) a report of the lid-switch being closed, which causes userspace to do an immediate suspend at boot. This commit delays getting the initial state and thus calling _LID for the first time until userspace opens the /dev/input/event# node. This ensures that all drivers will have had a chance to load and registerer their OpRegions before the first _LID call, fixing this issue. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
Родитель
39dae59d66
Коммит
84d3f6b764
|
@ -390,6 +390,7 @@ static void acpi_button_notify(struct acpi_device *device, u32 event)
|
|||
{
|
||||
struct acpi_button *button = acpi_driver_data(device);
|
||||
struct input_dev *input;
|
||||
int users;
|
||||
|
||||
switch (event) {
|
||||
case ACPI_FIXED_HARDWARE_EVENT:
|
||||
|
@ -398,6 +399,10 @@ static void acpi_button_notify(struct acpi_device *device, u32 event)
|
|||
case ACPI_BUTTON_NOTIFY_STATUS:
|
||||
input = button->input;
|
||||
if (button->type == ACPI_BUTTON_TYPE_LID) {
|
||||
mutex_lock(&button->input->mutex);
|
||||
users = button->input->users;
|
||||
mutex_unlock(&button->input->mutex);
|
||||
if (users)
|
||||
acpi_lid_update_state(device);
|
||||
} else {
|
||||
int keycode;
|
||||
|
@ -442,12 +447,24 @@ static int acpi_button_resume(struct device *dev)
|
|||
struct acpi_button *button = acpi_driver_data(device);
|
||||
|
||||
button->suspended = false;
|
||||
if (button->type == ACPI_BUTTON_TYPE_LID)
|
||||
if (button->type == ACPI_BUTTON_TYPE_LID && button->input->users)
|
||||
acpi_lid_initialize_state(device);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int acpi_lid_input_open(struct input_dev *input)
|
||||
{
|
||||
struct acpi_device *device = input_get_drvdata(input);
|
||||
struct acpi_button *button = acpi_driver_data(device);
|
||||
|
||||
button->last_state = !!acpi_lid_evaluate_state(device);
|
||||
button->last_time = ktime_get();
|
||||
acpi_lid_initialize_state(device);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int acpi_button_add(struct acpi_device *device)
|
||||
{
|
||||
struct acpi_button *button;
|
||||
|
@ -488,8 +505,7 @@ static int acpi_button_add(struct acpi_device *device)
|
|||
strcpy(name, ACPI_BUTTON_DEVICE_NAME_LID);
|
||||
sprintf(class, "%s/%s",
|
||||
ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_LID);
|
||||
button->last_state = !!acpi_lid_evaluate_state(device);
|
||||
button->last_time = ktime_get();
|
||||
input->open = acpi_lid_input_open;
|
||||
} else {
|
||||
printk(KERN_ERR PREFIX "Unsupported hid [%s]\n", hid);
|
||||
error = -ENODEV;
|
||||
|
@ -522,11 +538,11 @@ static int acpi_button_add(struct acpi_device *device)
|
|||
break;
|
||||
}
|
||||
|
||||
input_set_drvdata(input, device);
|
||||
error = input_register_device(input);
|
||||
if (error)
|
||||
goto err_remove_fs;
|
||||
if (button->type == ACPI_BUTTON_TYPE_LID) {
|
||||
acpi_lid_initialize_state(device);
|
||||
/*
|
||||
* This assumes there's only one lid device, or if there are
|
||||
* more we only care about the last one...
|
||||
|
|
Загрузка…
Ссылка в новой задаче