Commit f8df1601 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

Merge branches 'acpi-pm', 'acpi-battery' and 'acpi-ac'

Merge updates related to device power management, system sleep,
battery driver and AC driver for 5.16-rc1:

 - Check the states of all ACPI power resources during initialization
   to avoid dealing with power resources in unknown states (Rafael
   Wysocki).

 - Fix ACPI power resource issues related to sharing wakeup power
   resources (Rafael Wysocki).

 - Avoid registering redundant suspend_ops (Rafael Wysocki).

 - Report battery charging state as "full" if it appears to be over
   the design capacity (André Almeida).

 - Quirk GK45 mini PC to skip reading _PSR in the AC driver (Stefan
   Schaeckeler).

* acpi-pm:
  ACPI: PM: sleep: Do not set suspend_ops unnecessarily
  ACPI: PM: Turn off wakeup power resources on _DSW/_PSW errors
  ACPI: PM: Fix sharing of wakeup power resources
  ACPI: PM: Turn off unused wakeup power resources
  ACPI: PM: Check states of power resources during initialization

* acpi-battery:
  ACPI: battery: Accept charges over the design capacity as full

* acpi-ac:
  ACPI: AC: Quirk GK45 to skip reading _PSR
...@@ -61,6 +61,7 @@ static SIMPLE_DEV_PM_OPS(acpi_ac_pm, NULL, acpi_ac_resume); ...@@ -61,6 +61,7 @@ static SIMPLE_DEV_PM_OPS(acpi_ac_pm, NULL, acpi_ac_resume);
static int ac_sleep_before_get_state_ms; static int ac_sleep_before_get_state_ms;
static int ac_check_pmic = 1; static int ac_check_pmic = 1;
static int ac_only;
static struct acpi_driver acpi_ac_driver = { static struct acpi_driver acpi_ac_driver = {
.name = "ac", .name = "ac",
...@@ -93,6 +94,11 @@ static int acpi_ac_get_state(struct acpi_ac *ac) ...@@ -93,6 +94,11 @@ static int acpi_ac_get_state(struct acpi_ac *ac)
if (!ac) if (!ac)
return -EINVAL; return -EINVAL;
if (ac_only) {
ac->state = 1;
return 0;
}
status = acpi_evaluate_integer(ac->device->handle, "_PSR", NULL, status = acpi_evaluate_integer(ac->device->handle, "_PSR", NULL,
&ac->state); &ac->state);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
...@@ -200,6 +206,12 @@ static int __init ac_do_not_check_pmic_quirk(const struct dmi_system_id *d) ...@@ -200,6 +206,12 @@ static int __init ac_do_not_check_pmic_quirk(const struct dmi_system_id *d)
return 0; return 0;
} }
static int __init ac_only_quirk(const struct dmi_system_id *d)
{
ac_only = 1;
return 0;
}
/* Please keep this list alphabetically sorted */ /* Please keep this list alphabetically sorted */
static const struct dmi_system_id ac_dmi_table[] __initconst = { static const struct dmi_system_id ac_dmi_table[] __initconst = {
{ {
...@@ -209,6 +221,13 @@ static const struct dmi_system_id ac_dmi_table[] __initconst = { ...@@ -209,6 +221,13 @@ static const struct dmi_system_id ac_dmi_table[] __initconst = {
DMI_MATCH(DMI_PRODUCT_NAME, "EF20EA"), DMI_MATCH(DMI_PRODUCT_NAME, "EF20EA"),
}, },
}, },
{
/* Kodlix GK45 returning incorrect state */
.callback = ac_only_quirk,
.matches = {
DMI_MATCH(DMI_PRODUCT_NAME, "GK45"),
},
},
{ {
/* Lenovo Ideapad Miix 320, AXP288 PMIC, separate fuel-gauge */ /* Lenovo Ideapad Miix 320, AXP288 PMIC, separate fuel-gauge */
.callback = ac_do_not_check_pmic_quirk, .callback = ac_do_not_check_pmic_quirk,
......
...@@ -169,7 +169,7 @@ static int acpi_battery_is_charged(struct acpi_battery *battery) ...@@ -169,7 +169,7 @@ static int acpi_battery_is_charged(struct acpi_battery *battery)
return 1; return 1;
/* fallback to using design values for broken batteries */ /* fallback to using design values for broken batteries */
if (battery->design_capacity == battery->capacity_now) if (battery->design_capacity <= battery->capacity_now)
return 1; return 1;
/* we don't do any sort of metric based on percentages */ /* we don't do any sort of metric based on percentages */
......
...@@ -52,7 +52,6 @@ struct acpi_power_resource { ...@@ -52,7 +52,6 @@ struct acpi_power_resource {
u32 order; u32 order;
unsigned int ref_count; unsigned int ref_count;
u8 state; u8 state;
bool wakeup_enabled;
struct mutex resource_lock; struct mutex resource_lock;
struct list_head dependents; struct list_head dependents;
}; };
...@@ -615,20 +614,19 @@ int acpi_power_wakeup_list_init(struct list_head *list, int *system_level_p) ...@@ -615,20 +614,19 @@ int acpi_power_wakeup_list_init(struct list_head *list, int *system_level_p)
list_for_each_entry(entry, list, node) { list_for_each_entry(entry, list, node) {
struct acpi_power_resource *resource = entry->resource; struct acpi_power_resource *resource = entry->resource;
int result;
u8 state; u8 state;
mutex_lock(&resource->resource_lock); mutex_lock(&resource->resource_lock);
result = acpi_power_get_state(resource, &state); /*
if (result) { * Make sure that the power resource state and its reference
mutex_unlock(&resource->resource_lock); * counter value are consistent with each other.
return result; */
} if (!resource->ref_count &&
if (state == ACPI_POWER_RESOURCE_STATE_ON) { !acpi_power_get_state(resource, &state) &&
resource->ref_count++; state == ACPI_POWER_RESOURCE_STATE_ON)
resource->wakeup_enabled = true; __acpi_power_off(resource);
}
if (system_level > resource->system_level) if (system_level > resource->system_level)
system_level = resource->system_level; system_level = resource->system_level;
...@@ -711,7 +709,6 @@ int acpi_device_sleep_wake(struct acpi_device *dev, ...@@ -711,7 +709,6 @@ int acpi_device_sleep_wake(struct acpi_device *dev,
*/ */
int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state) int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state)
{ {
struct acpi_power_resource_entry *entry;
int err = 0; int err = 0;
if (!dev || !dev->wakeup.flags.valid) if (!dev || !dev->wakeup.flags.valid)
...@@ -722,33 +719,22 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state) ...@@ -722,33 +719,22 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state)
if (dev->wakeup.prepare_count++) if (dev->wakeup.prepare_count++)
goto out; goto out;
list_for_each_entry(entry, &dev->wakeup.resources, node) { err = acpi_power_on_list(&dev->wakeup.resources);
struct acpi_power_resource *resource = entry->resource; if (err) {
dev_err(&dev->dev, "Cannot turn on wakeup power resources\n");
mutex_lock(&resource->resource_lock); dev->wakeup.flags.valid = 0;
goto out;
if (!resource->wakeup_enabled) {
err = acpi_power_on_unlocked(resource);
if (!err)
resource->wakeup_enabled = true;
}
mutex_unlock(&resource->resource_lock);
if (err) {
dev_err(&dev->dev,
"Cannot turn wakeup power resources on\n");
dev->wakeup.flags.valid = 0;
goto out;
}
} }
/* /*
* Passing 3 as the third argument below means the device may be * Passing 3 as the third argument below means the device may be
* put into arbitrary power state afterward. * put into arbitrary power state afterward.
*/ */
err = acpi_device_sleep_wake(dev, 1, sleep_state, 3); err = acpi_device_sleep_wake(dev, 1, sleep_state, 3);
if (err) if (err) {
acpi_power_off_list(&dev->wakeup.resources);
dev->wakeup.prepare_count = 0; dev->wakeup.prepare_count = 0;
}
out: out:
mutex_unlock(&acpi_device_lock); mutex_unlock(&acpi_device_lock);
...@@ -771,39 +757,33 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev) ...@@ -771,39 +757,33 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev)
mutex_lock(&acpi_device_lock); mutex_lock(&acpi_device_lock);
if (--dev->wakeup.prepare_count > 0) if (dev->wakeup.prepare_count > 1) {
dev->wakeup.prepare_count--;
goto out; goto out;
}
/* /* Do nothing if wakeup power has not been enabled for this device. */
* Executing the code below even if prepare_count is already zero when if (!dev->wakeup.prepare_count)
* the function is called may be useful, for example for initialisation. goto out;
*/
if (dev->wakeup.prepare_count < 0)
dev->wakeup.prepare_count = 0;
err = acpi_device_sleep_wake(dev, 0, 0, 0); err = acpi_device_sleep_wake(dev, 0, 0, 0);
if (err) if (err)
goto out; goto out;
/*
* All of the power resources in the list need to be turned off even if
* there are errors.
*/
list_for_each_entry(entry, &dev->wakeup.resources, node) { list_for_each_entry(entry, &dev->wakeup.resources, node) {
struct acpi_power_resource *resource = entry->resource; int ret;
mutex_lock(&resource->resource_lock);
if (resource->wakeup_enabled) {
err = acpi_power_off_unlocked(resource);
if (!err)
resource->wakeup_enabled = false;
}
mutex_unlock(&resource->resource_lock);
if (err) { ret = acpi_power_off(entry->resource);
dev_err(&dev->dev, if (ret && !err)
"Cannot turn wakeup power resources off\n"); err = ret;
dev->wakeup.flags.valid = 0; }
break; if (err) {
} dev_err(&dev->dev, "Cannot turn off wakeup power resources\n");
dev->wakeup.flags.valid = 0;
} }
out: out:
...@@ -943,6 +923,7 @@ struct acpi_device *acpi_add_power_resource(acpi_handle handle) ...@@ -943,6 +923,7 @@ struct acpi_device *acpi_add_power_resource(acpi_handle handle)
union acpi_object acpi_object; union acpi_object acpi_object;
struct acpi_buffer buffer = { sizeof(acpi_object), &acpi_object }; struct acpi_buffer buffer = { sizeof(acpi_object), &acpi_object };
acpi_status status; acpi_status status;
u8 state_dummy;
int result; int result;
acpi_bus_get_device(handle, &device); acpi_bus_get_device(handle, &device);
...@@ -971,6 +952,10 @@ struct acpi_device *acpi_add_power_resource(acpi_handle handle) ...@@ -971,6 +952,10 @@ struct acpi_device *acpi_add_power_resource(acpi_handle handle)
resource->order = acpi_object.power_resource.resource_order; resource->order = acpi_object.power_resource.resource_order;
resource->state = ACPI_POWER_RESOURCE_STATE_UNKNOWN; resource->state = ACPI_POWER_RESOURCE_STATE_UNKNOWN;
/* Get the initial state or just flip it on if that fails. */
if (acpi_power_get_state(resource, &state_dummy))
__acpi_power_on(resource);
pr_info("%s [%s]\n", acpi_device_name(device), acpi_device_bid(device)); pr_info("%s [%s]\n", acpi_device_name(device), acpi_device_bid(device));
device->flags.match_driver = true; device->flags.match_driver = true;
......
...@@ -815,14 +815,18 @@ void __weak acpi_s2idle_setup(void) ...@@ -815,14 +815,18 @@ void __weak acpi_s2idle_setup(void)
static void acpi_sleep_suspend_setup(void) static void acpi_sleep_suspend_setup(void)
{ {
bool suspend_ops_needed = false;
int i; int i;
for (i = ACPI_STATE_S1; i < ACPI_STATE_S4; i++) for (i = ACPI_STATE_S1; i < ACPI_STATE_S4; i++)
if (acpi_sleep_state_supported(i)) if (acpi_sleep_state_supported(i)) {
sleep_states[i] = 1; sleep_states[i] = 1;
suspend_ops_needed = true;
}
suspend_set_ops(old_suspend_ordering ? if (suspend_ops_needed)
&acpi_suspend_ops_old : &acpi_suspend_ops); suspend_set_ops(old_suspend_ordering ?
&acpi_suspend_ops_old : &acpi_suspend_ops);
acpi_s2idle_setup(); acpi_s2idle_setup();
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment