forked from mirrors/linux
		
	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:
		
							parent
							
								
									39dae59d66
								
							
						
					
					
						commit
						84d3f6b764
					
				
					 1 changed files with 21 additions and 5 deletions
				
			
		| 
						 | 
				
			
			@ -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...
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue