Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f6bc0a16 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki
Browse files

Merge branches 'acpi-ec', 'acpi-video', 'acpi-button' and 'acpi-thermal'

* acpi-ec:
  ACPI / EC: Remove wrong ECDT correction quirks
  ACPI / EC: Cleanup boot EC code using acpi_ec_alloc()

* acpi-video:
  ACPI / video: Dummy acpi_video_register should return error code
  ACPI / video: skip evaluating _DOD when it does not exist
  ACPI / video: Thinkpad X201 Tablet needs video_detect_force_video

* acpi-button:
  ACPI / button: Add quirks for initial lid state notification
  ACPI / button: Refactor functions to eliminate redundant code
  ACPI / button: Remove initial lid state notification

* acpi-thermal:
  ACPI / thermal: Remove create_workqueue()
Loading
Loading
Loading
Loading
+3 −0
Original line number Original line Diff line number Diff line
@@ -1246,6 +1246,9 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video)
	union acpi_object *dod = NULL;
	union acpi_object *dod = NULL;
	union acpi_object *obj;
	union acpi_object *obj;


	if (!video->cap._DOD)
		return AE_NOT_EXIST;

	status = acpi_evaluate_object(video->device->handle, "_DOD", NULL, &buffer);
	status = acpi_evaluate_object(video->device->handle, "_DOD", NULL, &buffer);
	if (!ACPI_SUCCESS(status)) {
	if (!ACPI_SUCCESS(status)) {
		ACPI_EXCEPTION((AE_INFO, status, "Evaluating _DOD"));
		ACPI_EXCEPTION((AE_INFO, status, "Evaluating _DOD"));
+107 −42
Original line number Original line Diff line number Diff line
@@ -53,6 +53,10 @@
#define ACPI_BUTTON_DEVICE_NAME_LID	"Lid Switch"
#define ACPI_BUTTON_DEVICE_NAME_LID	"Lid Switch"
#define ACPI_BUTTON_TYPE_LID		0x05
#define ACPI_BUTTON_TYPE_LID		0x05


#define ACPI_BUTTON_LID_INIT_IGNORE	0x00
#define ACPI_BUTTON_LID_INIT_OPEN	0x01
#define ACPI_BUTTON_LID_INIT_METHOD	0x02

#define _COMPONENT		ACPI_BUTTON_COMPONENT
#define _COMPONENT		ACPI_BUTTON_COMPONENT
ACPI_MODULE_NAME("button");
ACPI_MODULE_NAME("button");


@@ -105,6 +109,7 @@ struct acpi_button {


static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier);
static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier);
static struct acpi_device *lid_device;
static struct acpi_device *lid_device;
static u8 lid_init_state = ACPI_BUTTON_LID_INIT_METHOD;


/* --------------------------------------------------------------------------
/* --------------------------------------------------------------------------
                              FS Interface (/proc)
                              FS Interface (/proc)
@@ -113,16 +118,52 @@ static struct acpi_device *lid_device;
static struct proc_dir_entry *acpi_button_dir;
static struct proc_dir_entry *acpi_button_dir;
static struct proc_dir_entry *acpi_lid_dir;
static struct proc_dir_entry *acpi_lid_dir;


static int acpi_lid_evaluate_state(struct acpi_device *device)
{
	unsigned long long lid_state;
	acpi_status status;

	status = acpi_evaluate_integer(device->handle, "_LID", NULL, &lid_state);
	if (ACPI_FAILURE(status))
		return -ENODEV;

	return lid_state ? 1 : 0;
}

static int acpi_lid_notify_state(struct acpi_device *device, int state)
{
	struct acpi_button *button = acpi_driver_data(device);
	int ret;

	/* input layer checks if event is redundant */
	input_report_switch(button->input, SW_LID, !state);
	input_sync(button->input);

	if (state)
		pm_wakeup_event(&device->dev, 0);

	ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, device);
	if (ret == NOTIFY_DONE)
		ret = blocking_notifier_call_chain(&acpi_lid_notifier, state,
						   device);
	if (ret == NOTIFY_DONE || ret == NOTIFY_OK) {
		/*
		 * It is also regarded as success if the notifier_chain
		 * returns NOTIFY_OK or NOTIFY_DONE.
		 */
		ret = 0;
	}
	return ret;
}

static int acpi_button_state_seq_show(struct seq_file *seq, void *offset)
static int acpi_button_state_seq_show(struct seq_file *seq, void *offset)
{
{
	struct acpi_device *device = seq->private;
	struct acpi_device *device = seq->private;
	acpi_status status;
	int state;
	unsigned long long state;


	status = acpi_evaluate_integer(device->handle, "_LID", NULL, &state);
	state = acpi_lid_evaluate_state(device);
	seq_printf(seq, "state:      %s\n",
	seq_printf(seq, "state:      %s\n",
		   ACPI_FAILURE(status) ? "unsupported" :
		   state < 0 ? "unsupported" : (state ? "open" : "closed"));
			(state ? "open" : "closed"));
	return 0;
	return 0;
}
}


@@ -231,51 +272,37 @@ EXPORT_SYMBOL(acpi_lid_notifier_unregister);


int acpi_lid_open(void)
int acpi_lid_open(void)
{
{
	acpi_status status;
	unsigned long long state;

	if (!lid_device)
	if (!lid_device)
		return -ENODEV;
		return -ENODEV;


	status = acpi_evaluate_integer(lid_device->handle, "_LID", NULL,
	return acpi_lid_evaluate_state(lid_device);
				       &state);
	if (ACPI_FAILURE(status))
		return -ENODEV;

	return !!state;
}
}
EXPORT_SYMBOL(acpi_lid_open);
EXPORT_SYMBOL(acpi_lid_open);


static int acpi_lid_send_state(struct acpi_device *device)
static int acpi_lid_update_state(struct acpi_device *device)
{
{
	struct acpi_button *button = acpi_driver_data(device);
	int state;
	unsigned long long state;
	acpi_status status;
	int ret;

	status = acpi_evaluate_integer(device->handle, "_LID", NULL, &state);
	if (ACPI_FAILURE(status))
		return -ENODEV;


	/* input layer checks if event is redundant */
	state = acpi_lid_evaluate_state(device);
	input_report_switch(button->input, SW_LID, !state);
	if (state < 0)
	input_sync(button->input);
		return state;


	if (state)
	return acpi_lid_notify_state(device, state);
		pm_wakeup_event(&device->dev, 0);
}


	ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, device);
static void acpi_lid_initialize_state(struct acpi_device *device)
	if (ret == NOTIFY_DONE)
{
		ret = blocking_notifier_call_chain(&acpi_lid_notifier, state,
	switch (lid_init_state) {
						   device);
	case ACPI_BUTTON_LID_INIT_OPEN:
	if (ret == NOTIFY_DONE || ret == NOTIFY_OK) {
		(void)acpi_lid_notify_state(device, 1);
		/*
		break;
		 * It is also regarded as success if the notifier_chain
	case ACPI_BUTTON_LID_INIT_METHOD:
		 * returns NOTIFY_OK or NOTIFY_DONE.
		(void)acpi_lid_update_state(device);
		 */
		break;
		ret = 0;
	case ACPI_BUTTON_LID_INIT_IGNORE:
	default:
		break;
	}
	}
	return ret;
}
}


static void acpi_button_notify(struct acpi_device *device, u32 event)
static void acpi_button_notify(struct acpi_device *device, u32 event)
@@ -290,7 +317,7 @@ static void acpi_button_notify(struct acpi_device *device, u32 event)
	case ACPI_BUTTON_NOTIFY_STATUS:
	case ACPI_BUTTON_NOTIFY_STATUS:
		input = button->input;
		input = button->input;
		if (button->type == ACPI_BUTTON_TYPE_LID) {
		if (button->type == ACPI_BUTTON_TYPE_LID) {
			acpi_lid_send_state(device);
			acpi_lid_update_state(device);
		} else {
		} else {
			int keycode;
			int keycode;


@@ -335,7 +362,7 @@ static int acpi_button_resume(struct device *dev)


	button->suspended = false;
	button->suspended = false;
	if (button->type == ACPI_BUTTON_TYPE_LID)
	if (button->type == ACPI_BUTTON_TYPE_LID)
		return acpi_lid_send_state(device);
		acpi_lid_initialize_state(device);
	return 0;
	return 0;
}
}
#endif
#endif
@@ -416,7 +443,7 @@ static int acpi_button_add(struct acpi_device *device)
	if (error)
	if (error)
		goto err_remove_fs;
		goto err_remove_fs;
	if (button->type == ACPI_BUTTON_TYPE_LID) {
	if (button->type == ACPI_BUTTON_TYPE_LID) {
		acpi_lid_send_state(device);
		acpi_lid_initialize_state(device);
		/*
		/*
		 * This assumes there's only one lid device, or if there are
		 * This assumes there's only one lid device, or if there are
		 * more we only care about the last one...
		 * more we only care about the last one...
@@ -446,4 +473,42 @@ static int acpi_button_remove(struct acpi_device *device)
	return 0;
	return 0;
}
}


static int param_set_lid_init_state(const char *val, struct kernel_param *kp)
{
	int result = 0;

	if (!strncmp(val, "open", sizeof("open") - 1)) {
		lid_init_state = ACPI_BUTTON_LID_INIT_OPEN;
		pr_info("Notify initial lid state as open\n");
	} else if (!strncmp(val, "method", sizeof("method") - 1)) {
		lid_init_state = ACPI_BUTTON_LID_INIT_METHOD;
		pr_info("Notify initial lid state with _LID return value\n");
	} else if (!strncmp(val, "ignore", sizeof("ignore") - 1)) {
		lid_init_state = ACPI_BUTTON_LID_INIT_IGNORE;
		pr_info("Do not notify initial lid state\n");
	} else
		result = -EINVAL;
	return result;
}

static int param_get_lid_init_state(char *buffer, struct kernel_param *kp)
{
	switch (lid_init_state) {
	case ACPI_BUTTON_LID_INIT_OPEN:
		return sprintf(buffer, "open");
	case ACPI_BUTTON_LID_INIT_METHOD:
		return sprintf(buffer, "method");
	case ACPI_BUTTON_LID_INIT_IGNORE:
		return sprintf(buffer, "ignore");
	default:
		return sprintf(buffer, "invalid");
	}
	return 0;
}

module_param_call(lid_init_state,
		  param_set_lid_init_state, param_get_lid_init_state,
		  NULL, 0644);
MODULE_PARM_DESC(lid_init_state, "Behavior for reporting LID initial state");

module_acpi_driver(acpi_button_driver);
module_acpi_driver(acpi_button_driver);
+53 −53
Original line number Original line Diff line number Diff line
@@ -1359,13 +1359,9 @@ static void ec_remove_handlers(struct acpi_ec *ec)
	}
	}
}
}


static int acpi_ec_add(struct acpi_device *device)
static struct acpi_ec *acpi_ec_alloc(void)
{
{
	struct acpi_ec *ec = NULL;
	struct acpi_ec *ec;
	int ret;

	strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME);
	strcpy(acpi_device_class(device), ACPI_EC_CLASS);


	/* Check for boot EC */
	/* Check for boot EC */
	if (boot_ec) {
	if (boot_ec) {
@@ -1376,9 +1372,21 @@ static int acpi_ec_add(struct acpi_device *device)
			first_ec = NULL;
			first_ec = NULL;
	} else {
	} else {
		ec = make_acpi_ec();
		ec = make_acpi_ec();
	}
	return ec;
}

static int acpi_ec_add(struct acpi_device *device)
{
	struct acpi_ec *ec = NULL;
	int ret;

	strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME);
	strcpy(acpi_device_class(device), ACPI_EC_CLASS);

	ec = acpi_ec_alloc();
	if (!ec)
	if (!ec)
		return -ENOMEM;
		return -ENOMEM;
	}
	if (ec_parse_device(device->handle, 0, ec, NULL) !=
	if (ec_parse_device(device->handle, 0, ec, NULL) !=
		AE_CTRL_TERMINATE) {
		AE_CTRL_TERMINATE) {
			kfree(ec);
			kfree(ec);
@@ -1465,27 +1473,31 @@ static const struct acpi_device_id ec_device_ids[] = {
int __init acpi_ec_dsdt_probe(void)
int __init acpi_ec_dsdt_probe(void)
{
{
	acpi_status status;
	acpi_status status;
	struct acpi_ec *ec;
	int ret;


	if (boot_ec)
	ec = acpi_ec_alloc();
		return 0;
	if (!ec)

		return -ENOMEM;
	/*
	/*
	 * Finding EC from DSDT if there is no ECDT EC available. When this
	 * Finding EC from DSDT if there is no ECDT EC available. When this
	 * function is invoked, ACPI tables have been fully loaded, we can
	 * function is invoked, ACPI tables have been fully loaded, we can
	 * walk namespace now.
	 * walk namespace now.
	 */
	 */
	boot_ec = make_acpi_ec();
	if (!boot_ec)
		return -ENOMEM;
	status = acpi_get_devices(ec_device_ids[0].id,
	status = acpi_get_devices(ec_device_ids[0].id,
				  ec_parse_device, boot_ec, NULL);
				  ec_parse_device, ec, NULL);
	if (ACPI_FAILURE(status) || !boot_ec->handle)
	if (ACPI_FAILURE(status) || !ec->handle) {
		return -ENODEV;
		ret = -ENODEV;
	if (!ec_install_handlers(boot_ec)) {
		goto error;
		first_ec = boot_ec;
		return 0;
	}
	}
	return -EFAULT;
	ret = ec_install_handlers(ec);

error:
	if (ret)
		kfree(ec);
	else
		first_ec = boot_ec = ec;
	return ret;
}
}


#if 0
#if 0
@@ -1529,6 +1541,11 @@ static int ec_clear_on_resume(const struct dmi_system_id *id)
	return 0;
	return 0;
}
}


/*
 * Some ECDTs contain wrong register addresses.
 * MSI MS-171F
 * https://bugzilla.kernel.org/show_bug.cgi?id=12461
 */
static int ec_correct_ecdt(const struct dmi_system_id *id)
static int ec_correct_ecdt(const struct dmi_system_id *id)
{
{
	pr_debug("Detected system needing ECDT address correction.\n");
	pr_debug("Detected system needing ECDT address correction.\n");
@@ -1537,16 +1554,6 @@ static int ec_correct_ecdt(const struct dmi_system_id *id)
}
}


static struct dmi_system_id ec_dmi_table[] __initdata = {
static struct dmi_system_id ec_dmi_table[] __initdata = {
	{
	ec_correct_ecdt, "Asus L4R", {
	DMI_MATCH(DMI_BIOS_VERSION, "1008.006"),
	DMI_MATCH(DMI_PRODUCT_NAME, "L4R"),
	DMI_MATCH(DMI_BOARD_NAME, "L4R") }, NULL},
	{
	ec_correct_ecdt, "Asus M6R", {
	DMI_MATCH(DMI_BIOS_VERSION, "0207"),
	DMI_MATCH(DMI_PRODUCT_NAME, "M6R"),
	DMI_MATCH(DMI_BOARD_NAME, "M6R") }, NULL},
	{
	{
	ec_correct_ecdt, "MSI MS-171F", {
	ec_correct_ecdt, "MSI MS-171F", {
	DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star"),
	DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star"),
@@ -1559,12 +1566,13 @@ static struct dmi_system_id ec_dmi_table[] __initdata = {


int __init acpi_ec_ecdt_probe(void)
int __init acpi_ec_ecdt_probe(void)
{
{
	int ret = 0;
	int ret;
	acpi_status status;
	acpi_status status;
	struct acpi_table_ecdt *ecdt_ptr;
	struct acpi_table_ecdt *ecdt_ptr;
	struct acpi_ec *ec;


	boot_ec = make_acpi_ec();
	ec = acpi_ec_alloc();
	if (!boot_ec)
	if (!ec)
		return -ENOMEM;
		return -ENOMEM;
	/*
	/*
	 * Generate a boot ec context
	 * Generate a boot ec context
@@ -1588,28 +1596,20 @@ int __init acpi_ec_ecdt_probe(void)


	pr_info("EC description table is found, configuring boot EC\n");
	pr_info("EC description table is found, configuring boot EC\n");
	if (EC_FLAGS_CORRECT_ECDT) {
	if (EC_FLAGS_CORRECT_ECDT) {
		/*
		ec->command_addr = ecdt_ptr->data.address;
		 * Asus L4R, Asus M6R
		ec->data_addr = ecdt_ptr->control.address;
		 * https://bugzilla.kernel.org/show_bug.cgi?id=9399
		 * MSI MS-171F
		 * https://bugzilla.kernel.org/show_bug.cgi?id=12461
		 */
		boot_ec->command_addr = ecdt_ptr->data.address;
		boot_ec->data_addr = ecdt_ptr->control.address;
	} else {
	} else {
		boot_ec->command_addr = ecdt_ptr->control.address;
		ec->command_addr = ecdt_ptr->control.address;
		boot_ec->data_addr = ecdt_ptr->data.address;
		ec->data_addr = ecdt_ptr->data.address;
	}
	boot_ec->gpe = ecdt_ptr->gpe;
	boot_ec->handle = ACPI_ROOT_OBJECT;
	ret = ec_install_handlers(boot_ec);
	if (!ret)
		first_ec = boot_ec;
error:
	if (ret) {
		kfree(boot_ec);
		boot_ec = NULL;
	}
	}
	ec->gpe = ecdt_ptr->gpe;
	ec->handle = ACPI_ROOT_OBJECT;
	ret = ec_install_handlers(ec);
error:
	if (ret)
		kfree(ec);
	else
		first_ec = boot_ec = ec;
	return ret;
	return ret;
}
}


+2 −1
Original line number Original line Diff line number Diff line
@@ -1259,7 +1259,8 @@ static int __init acpi_thermal_init(void)
		return -ENODEV;
		return -ENODEV;
	}
	}


	acpi_thermal_pm_queue = create_workqueue("acpi_thermal_pm");
	acpi_thermal_pm_queue = alloc_workqueue("acpi_thermal_pm",
						WQ_HIGHPRI | WQ_MEM_RECLAIM, 0);
	if (!acpi_thermal_pm_queue)
	if (!acpi_thermal_pm_queue)
		return -ENODEV;
		return -ENODEV;


+8 −0
Original line number Original line Diff line number Diff line
@@ -167,6 +167,14 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
		DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X201s"),
		DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X201s"),
		},
		},
	},
	},
        {
         .callback = video_detect_force_video,
         .ident = "ThinkPad X201T",
         .matches = {
                DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
                DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X201T"),
                },
        },


	/* The native backlight controls do not work on some older machines */
	/* The native backlight controls do not work on some older machines */
	{
	{
Loading