forked from Minki/linux
More ACPI updates for 6.1-rc1
- Fix ACPI device object reference counting in (recently updated) skl_int3472_fill_clk_pdata() (Andy Shevchenko). - Fix a memory leak in APEI by avoiding to add a task_work to kernel threads running when an asynchronous error is detected (Shuai Xue). - Add ACPI support for handling system wakeups via GPIO wake capable IRQs in addition to GPEs (Raul E Rangel). - Make the system reboot code put ACPI-enabled systems into the S5 (system off) state which is necessary for some platforms to work as expected (Kai-Heng Feng). - Make the white space usage in the ACPI thermal driver more consistent and drop redundant code from it (Rafael Wysocki). -----BEGIN PGP SIGNATURE----- iQJGBAABCAAwFiEE4fcc61cGeeHD/fCwgsRv/nhiVHEFAmNEVJMSHHJqd0Byand5 c29ja2kubmV0AAoJEILEb/54YlRxQ1YP/0abCMN+M3TVoLC2CKr4ejVUbDlzpFpx NN7CQVl6rCO68XN3JiYjlxasEl3gWI2SKNsjbN8flIXsIYh1WYgDaEHlN1urIzXW 0dpMa8lryMashWYYt5FNv05vRW33xta4HwmnHwqr8ASp7MClvB9I+s94CMZryeEh UTqIu9HPJ/I8VZlNgZHHisQkL1IOT+3QRbVMJr7QMkAKy01UiJco0e962T+h3nBU RPSg0FctjorfCnPO5hmjVA99AAOskfB1HSh3CRYy9TSrx4MFEAsttxNeEofNHGTn Gyjgugy5DJYvvfe0A/BgWWqwiUXoLmfRIjeARuv+JL1vPQfSJaF7PqnNPPAhexLG 62wF1CE38zKSbbKAg3fNywXQnXnuBLPlNTUxt3tH3PBdI+un1zuH5/9C0YgkRlRO Pwv3tAs52HKFIqenHz2axxZQrQObrHvSiJJN+q1TlURt5QHyb1n6FJYg/1MCQ6fz 5etirjbptTD+q2YAqDodGge9HaHvKndrUi3oAs0wsKWFKVlawtqzGPeqNkRNTIYt RU4kEtCcOkUgwNmKRRly4nWf2UgF/YxGugX1FW3Y7p6nHj7VY7BnaQaTXbtLaTXU PTbT7GZKSIcGQO1xtxDSL3uXYVurqyr4LtM8JBbJSjbwNKAJuVpzgx6iDdg08vVc mg/pOlmgMpoO =pwnm -----END PGP SIGNATURE----- Merge tag 'acpi-6.1-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm Pull more ACPI updates from Rafael Wysocki: "These fix two issues, in APEI and in the int3472 driver, clean up the ACPI thermal driver, add ACPI support for non-GPE system wakeup events and make the system reboot code use the S5 (system off) state by default. Specifics: - Fix ACPI device object reference counting in (recently updated) skl_int3472_fill_clk_pdata() (Andy Shevchenko). - Fix a memory leak in APEI by avoiding to add a task_work to kernel threads running when an asynchronous error is detected (Shuai Xue). - Add ACPI support for handling system wakeups via GPIO wake capable IRQs in addition to GPEs (Raul E Rangel). - Make the system reboot code put ACPI-enabled systems into the S5 (system off) state which is necessary for some platforms to work as expected (Kai-Heng Feng). - Make the white space usage in the ACPI thermal driver more consistent and drop redundant code from it (Rafael Wysocki)" * tag 'acpi-6.1-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: ACPI: thermal: Drop some redundant code ACPI: thermal: Drop redundant parens from expressions ACPI: thermal: Use white space more consistently platform/x86: int3472: Don't leak reference on error ACPI: APEI: do not add task_work to kernel thread to avoid memory leak PM: ACPI: reboot: Reinstate S5 for reboot kernel/reboot: Add SYS_OFF_MODE_RESTART_PREPARE mode ACPI: PM: Take wake IRQ into consideration when entering suspend-to-idle i2c: acpi: Use ACPI wake capability bit to set wake_irq ACPI: resources: Add wake_capable parameter to acpi_dev_irq_flags gpiolib: acpi: Add wake_capable variants of acpi_dev_gpio_irq_get
This commit is contained in:
commit
3a1e24fa70
@ -985,7 +985,7 @@ static void ghes_proc_in_irq(struct irq_work *irq_work)
|
||||
ghes_estatus_cache_add(generic, estatus);
|
||||
}
|
||||
|
||||
if (task_work_pending && current->mm != &init_mm) {
|
||||
if (task_work_pending && current->mm) {
|
||||
estatus_node->task_work.func = ghes_kick_task_work;
|
||||
estatus_node->task_work_cpu = smp_processor_id();
|
||||
ret = task_work_add(current, &estatus_node->task_work,
|
||||
|
@ -687,7 +687,22 @@ static int acpi_dev_pm_get_state(struct device *dev, struct acpi_device *adev,
|
||||
d_min = ret;
|
||||
wakeup = device_may_wakeup(dev) && adev->wakeup.flags.valid
|
||||
&& adev->wakeup.sleep_state >= target_state;
|
||||
} else if (device_may_wakeup(dev) && dev->power.wakeirq) {
|
||||
/*
|
||||
* The ACPI subsystem doesn't manage the wake bit for IRQs
|
||||
* defined with ExclusiveAndWake and SharedAndWake. Instead we
|
||||
* expect them to be managed via the PM subsystem. Drivers
|
||||
* should call dev_pm_set_wake_irq to register an IRQ as a wake
|
||||
* source.
|
||||
*
|
||||
* If a device has a wake IRQ attached we need to check the
|
||||
* _S0W method to get the correct wake D-state. Otherwise we
|
||||
* end up putting the device into D3Cold which will more than
|
||||
* likely disable wake functionality.
|
||||
*/
|
||||
wakeup = true;
|
||||
} else {
|
||||
/* ACPI GPE is specified in _PRW. */
|
||||
wakeup = adev->wakeup.flags.valid;
|
||||
}
|
||||
|
||||
|
@ -147,6 +147,7 @@ struct acpi_irq_parse_one_ctx {
|
||||
* @polarity: polarity attributes of hwirq
|
||||
* @polarity: polarity attributes of hwirq
|
||||
* @shareable: shareable attributes of hwirq
|
||||
* @wake_capable: wake capable attribute of hwirq
|
||||
* @ctx: acpi_irq_parse_one_ctx updated by this function
|
||||
*
|
||||
* Description:
|
||||
@ -156,12 +157,13 @@ struct acpi_irq_parse_one_ctx {
|
||||
static inline void acpi_irq_parse_one_match(struct fwnode_handle *fwnode,
|
||||
u32 hwirq, u8 triggering,
|
||||
u8 polarity, u8 shareable,
|
||||
u8 wake_capable,
|
||||
struct acpi_irq_parse_one_ctx *ctx)
|
||||
{
|
||||
if (!fwnode)
|
||||
return;
|
||||
ctx->rc = 0;
|
||||
*ctx->res_flags = acpi_dev_irq_flags(triggering, polarity, shareable);
|
||||
*ctx->res_flags = acpi_dev_irq_flags(triggering, polarity, shareable, wake_capable);
|
||||
ctx->fwspec->fwnode = fwnode;
|
||||
ctx->fwspec->param[0] = hwirq;
|
||||
ctx->fwspec->param[1] = acpi_dev_get_irq_type(triggering, polarity);
|
||||
@ -204,7 +206,7 @@ static acpi_status acpi_irq_parse_one_cb(struct acpi_resource *ares,
|
||||
fwnode = acpi_get_gsi_domain_id(irq->interrupts[ctx->index]);
|
||||
acpi_irq_parse_one_match(fwnode, irq->interrupts[ctx->index],
|
||||
irq->triggering, irq->polarity,
|
||||
irq->shareable, ctx);
|
||||
irq->shareable, irq->wake_capable, ctx);
|
||||
return AE_CTRL_TERMINATE;
|
||||
case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
|
||||
eirq = &ares->data.extended_irq;
|
||||
@ -218,7 +220,7 @@ static acpi_status acpi_irq_parse_one_cb(struct acpi_resource *ares,
|
||||
eirq->interrupts[ctx->index]);
|
||||
acpi_irq_parse_one_match(fwnode, eirq->interrupts[ctx->index],
|
||||
eirq->triggering, eirq->polarity,
|
||||
eirq->shareable, ctx);
|
||||
eirq->shareable, eirq->wake_capable, ctx);
|
||||
return AE_CTRL_TERMINATE;
|
||||
}
|
||||
|
||||
|
@ -336,8 +336,9 @@ EXPORT_SYMBOL_GPL(acpi_dev_resource_ext_address_space);
|
||||
* @triggering: Triggering type as provided by ACPI.
|
||||
* @polarity: Interrupt polarity as provided by ACPI.
|
||||
* @shareable: Whether or not the interrupt is shareable.
|
||||
* @wake_capable: Wake capability as provided by ACPI.
|
||||
*/
|
||||
unsigned long acpi_dev_irq_flags(u8 triggering, u8 polarity, u8 shareable)
|
||||
unsigned long acpi_dev_irq_flags(u8 triggering, u8 polarity, u8 shareable, u8 wake_capable)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
@ -351,6 +352,9 @@ unsigned long acpi_dev_irq_flags(u8 triggering, u8 polarity, u8 shareable)
|
||||
if (shareable == ACPI_SHARED)
|
||||
flags |= IORESOURCE_IRQ_SHAREABLE;
|
||||
|
||||
if (wake_capable == ACPI_WAKE_CAPABLE)
|
||||
flags |= IORESOURCE_IRQ_WAKECAPABLE;
|
||||
|
||||
return flags | IORESOURCE_IRQ;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_dev_irq_flags);
|
||||
@ -468,7 +472,7 @@ static bool acpi_dev_irq_override(u32 gsi, u8 triggering, u8 polarity,
|
||||
|
||||
static void acpi_dev_get_irqresource(struct resource *res, u32 gsi,
|
||||
u8 triggering, u8 polarity, u8 shareable,
|
||||
bool check_override)
|
||||
u8 wake_capable, bool check_override)
|
||||
{
|
||||
int irq, p, t;
|
||||
|
||||
@ -501,7 +505,7 @@ static void acpi_dev_get_irqresource(struct resource *res, u32 gsi,
|
||||
}
|
||||
}
|
||||
|
||||
res->flags = acpi_dev_irq_flags(triggering, polarity, shareable);
|
||||
res->flags = acpi_dev_irq_flags(triggering, polarity, shareable, wake_capable);
|
||||
irq = acpi_register_gsi(NULL, gsi, triggering, polarity);
|
||||
if (irq >= 0) {
|
||||
res->start = irq;
|
||||
@ -549,7 +553,8 @@ bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index,
|
||||
}
|
||||
acpi_dev_get_irqresource(res, irq->interrupts[index],
|
||||
irq->triggering, irq->polarity,
|
||||
irq->shareable, true);
|
||||
irq->shareable, irq->wake_capable,
|
||||
true);
|
||||
break;
|
||||
case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
|
||||
ext_irq = &ares->data.extended_irq;
|
||||
@ -560,7 +565,8 @@ bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index,
|
||||
if (is_gsi(ext_irq))
|
||||
acpi_dev_get_irqresource(res, ext_irq->interrupts[index],
|
||||
ext_irq->triggering, ext_irq->polarity,
|
||||
ext_irq->shareable, false);
|
||||
ext_irq->shareable, ext_irq->wake_capable,
|
||||
false);
|
||||
else
|
||||
irqresource_disabled(res, 0);
|
||||
break;
|
||||
|
@ -1088,6 +1088,14 @@ int __init acpi_sleep_init(void)
|
||||
register_sys_off_handler(SYS_OFF_MODE_POWER_OFF,
|
||||
SYS_OFF_PRIO_FIRMWARE,
|
||||
acpi_power_off, NULL);
|
||||
|
||||
/*
|
||||
* Windows uses S5 for reboot, so some BIOSes depend on it to
|
||||
* perform proper reboot.
|
||||
*/
|
||||
register_sys_off_handler(SYS_OFF_MODE_RESTART_PREPARE,
|
||||
SYS_OFF_PRIO_FIRMWARE,
|
||||
acpi_power_off_prepare, NULL);
|
||||
} else {
|
||||
acpi_no_s5 = true;
|
||||
}
|
||||
|
@ -262,7 +262,7 @@ do { \
|
||||
|
||||
static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
acpi_status status;
|
||||
unsigned long long tmp;
|
||||
struct acpi_handle_list devices;
|
||||
int valid = 0;
|
||||
@ -270,8 +270,7 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
|
||||
|
||||
/* Critical Shutdown */
|
||||
if (flag & ACPI_TRIPS_CRITICAL) {
|
||||
status = acpi_evaluate_integer(tz->device->handle,
|
||||
"_CRT", NULL, &tmp);
|
||||
status = acpi_evaluate_integer(tz->device->handle, "_CRT", NULL, &tmp);
|
||||
tz->trips.critical.temperature = tmp;
|
||||
/*
|
||||
* Treat freezing temperatures as invalid as well; some
|
||||
@ -284,8 +283,7 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
|
||||
acpi_handle_debug(tz->device->handle,
|
||||
"No critical threshold\n");
|
||||
} else if (tmp <= 2732) {
|
||||
pr_info(FW_BUG "Invalid critical threshold (%llu)\n",
|
||||
tmp);
|
||||
pr_info(FW_BUG "Invalid critical threshold (%llu)\n", tmp);
|
||||
tz->trips.critical.flags.valid = 0;
|
||||
} else {
|
||||
tz->trips.critical.flags.valid = 1;
|
||||
@ -312,8 +310,7 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
|
||||
|
||||
/* Critical Sleep (optional) */
|
||||
if (flag & ACPI_TRIPS_HOT) {
|
||||
status = acpi_evaluate_integer(tz->device->handle,
|
||||
"_HOT", NULL, &tmp);
|
||||
status = acpi_evaluate_integer(tz->device->handle, "_HOT", NULL, &tmp);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
tz->trips.hot.flags.valid = 0;
|
||||
acpi_handle_debug(tz->device->handle,
|
||||
@ -329,7 +326,7 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
|
||||
|
||||
/* Passive (optional) */
|
||||
if (((flag & ACPI_TRIPS_PASSIVE) && tz->trips.passive.flags.valid) ||
|
||||
(flag == ACPI_TRIPS_INIT)) {
|
||||
flag == ACPI_TRIPS_INIT) {
|
||||
valid = tz->trips.passive.flags.valid;
|
||||
if (psv == -1) {
|
||||
status = AE_SUPPORT;
|
||||
@ -341,29 +338,28 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
|
||||
"_PSV", NULL, &tmp);
|
||||
}
|
||||
|
||||
if (ACPI_FAILURE(status))
|
||||
if (ACPI_FAILURE(status)) {
|
||||
tz->trips.passive.flags.valid = 0;
|
||||
else {
|
||||
} else {
|
||||
tz->trips.passive.temperature = tmp;
|
||||
tz->trips.passive.flags.valid = 1;
|
||||
if (flag == ACPI_TRIPS_INIT) {
|
||||
status = acpi_evaluate_integer(
|
||||
tz->device->handle, "_TC1",
|
||||
NULL, &tmp);
|
||||
status = acpi_evaluate_integer(tz->device->handle,
|
||||
"_TC1", NULL, &tmp);
|
||||
if (ACPI_FAILURE(status))
|
||||
tz->trips.passive.flags.valid = 0;
|
||||
else
|
||||
tz->trips.passive.tc1 = tmp;
|
||||
status = acpi_evaluate_integer(
|
||||
tz->device->handle, "_TC2",
|
||||
NULL, &tmp);
|
||||
|
||||
status = acpi_evaluate_integer(tz->device->handle,
|
||||
"_TC2", NULL, &tmp);
|
||||
if (ACPI_FAILURE(status))
|
||||
tz->trips.passive.flags.valid = 0;
|
||||
else
|
||||
tz->trips.passive.tc2 = tmp;
|
||||
status = acpi_evaluate_integer(
|
||||
tz->device->handle, "_TSP",
|
||||
NULL, &tmp);
|
||||
|
||||
status = acpi_evaluate_integer(tz->device->handle,
|
||||
"_TSP", NULL, &tmp);
|
||||
if (ACPI_FAILURE(status))
|
||||
tz->trips.passive.flags.valid = 0;
|
||||
else
|
||||
@ -379,9 +375,9 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
|
||||
acpi_handle_info(tz->device->handle,
|
||||
"Invalid passive threshold\n");
|
||||
tz->trips.passive.flags.valid = 0;
|
||||
}
|
||||
else
|
||||
} else {
|
||||
tz->trips.passive.flags.valid = 1;
|
||||
}
|
||||
|
||||
if (memcmp(&tz->trips.passive.devices, &devices,
|
||||
sizeof(struct acpi_handle_list))) {
|
||||
@ -403,7 +399,7 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
|
||||
if (act == -1)
|
||||
break; /* disable all active trip points */
|
||||
|
||||
if ((flag == ACPI_TRIPS_INIT) || ((flag & ACPI_TRIPS_ACTIVE) &&
|
||||
if (flag == ACPI_TRIPS_INIT || ((flag & ACPI_TRIPS_ACTIVE) &&
|
||||
tz->trips.active[i].flags.valid)) {
|
||||
status = acpi_evaluate_integer(tz->device->handle,
|
||||
name, NULL, &tmp);
|
||||
@ -411,11 +407,12 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
|
||||
tz->trips.active[i].flags.valid = 0;
|
||||
if (i == 0)
|
||||
break;
|
||||
|
||||
if (act <= 0)
|
||||
break;
|
||||
|
||||
if (i == 1)
|
||||
tz->trips.active[0].temperature =
|
||||
celsius_to_deci_kelvin(act);
|
||||
tz->trips.active[0].temperature = celsius_to_deci_kelvin(act);
|
||||
else
|
||||
/*
|
||||
* Don't allow override higher than
|
||||
@ -426,6 +423,7 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
|
||||
celsius_to_deci_kelvin(act) ?
|
||||
tz->trips.active[i-2].temperature :
|
||||
celsius_to_deci_kelvin(act));
|
||||
|
||||
break;
|
||||
} else {
|
||||
tz->trips.active[i].temperature = tmp;
|
||||
@ -442,9 +440,9 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
|
||||
acpi_handle_info(tz->device->handle,
|
||||
"Invalid active%d threshold\n", i);
|
||||
tz->trips.active[i].flags.valid = 0;
|
||||
}
|
||||
else
|
||||
} else {
|
||||
tz->trips.active[i].flags.valid = 1;
|
||||
}
|
||||
|
||||
if (memcmp(&tz->trips.active[i].devices, &devices,
|
||||
sizeof(struct acpi_handle_list))) {
|
||||
@ -465,8 +463,8 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
|
||||
memset(&devices, 0, sizeof(devices));
|
||||
status = acpi_evaluate_reference(tz->device->handle, "_TZD",
|
||||
NULL, &devices);
|
||||
if (ACPI_SUCCESS(status)
|
||||
&& memcmp(&tz->devices, &devices, sizeof(devices))) {
|
||||
if (ACPI_SUCCESS(status) &&
|
||||
memcmp(&tz->devices, &devices, sizeof(devices))) {
|
||||
tz->devices = devices;
|
||||
ACPI_THERMAL_TRIPS_EXCEPTION(flag, tz, "device");
|
||||
}
|
||||
@ -548,8 +546,7 @@ static int thermal_get_trip_type(struct thermal_zone_device *thermal,
|
||||
trip--;
|
||||
}
|
||||
|
||||
for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
|
||||
tz->trips.active[i].flags.valid; i++) {
|
||||
for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE && tz->trips.active[i].flags.valid; i++) {
|
||||
if (!trip) {
|
||||
*type = THERMAL_TRIP_ACTIVE;
|
||||
return 0;
|
||||
@ -623,7 +620,8 @@ static int thermal_get_crit_temp(struct thermal_zone_device *thermal,
|
||||
tz->trips.critical.temperature,
|
||||
tz->kelvin_offset);
|
||||
return 0;
|
||||
} else
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -657,9 +655,8 @@ static int thermal_get_trend(struct thermal_zone_device *thermal,
|
||||
* tz->temperature has already been updated by generic thermal layer,
|
||||
* before this callback being invoked
|
||||
*/
|
||||
i = (tz->trips.passive.tc1 * (tz->temperature - tz->last_temperature))
|
||||
+ (tz->trips.passive.tc2
|
||||
* (tz->temperature - tz->trips.passive.temperature));
|
||||
i = tz->trips.passive.tc1 * (tz->temperature - tz->last_temperature) +
|
||||
tz->trips.passive.tc2 * (tz->temperature - tz->trips.passive.temperature);
|
||||
|
||||
if (i > 0)
|
||||
*trend = THERMAL_TREND_RAISING;
|
||||
@ -667,6 +664,7 @@ static int thermal_get_trend(struct thermal_zone_device *thermal,
|
||||
*trend = THERMAL_TREND_DROPPING;
|
||||
else
|
||||
*trend = THERMAL_TREND_STABLE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -711,22 +709,23 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
|
||||
|
||||
if (tz->trips.passive.flags.valid) {
|
||||
trip++;
|
||||
for (i = 0; i < tz->trips.passive.devices.count;
|
||||
i++) {
|
||||
for (i = 0; i < tz->trips.passive.devices.count; i++) {
|
||||
handle = tz->trips.passive.devices.handles[i];
|
||||
dev = acpi_fetch_acpi_dev(handle);
|
||||
if (dev != device)
|
||||
continue;
|
||||
|
||||
if (bind)
|
||||
result =
|
||||
thermal_zone_bind_cooling_device
|
||||
(thermal, trip, cdev,
|
||||
THERMAL_NO_LIMIT, THERMAL_NO_LIMIT,
|
||||
result = thermal_zone_bind_cooling_device(
|
||||
thermal, trip, cdev,
|
||||
THERMAL_NO_LIMIT,
|
||||
THERMAL_NO_LIMIT,
|
||||
THERMAL_WEIGHT_DEFAULT);
|
||||
else
|
||||
result =
|
||||
thermal_zone_unbind_cooling_device
|
||||
(thermal, trip, cdev);
|
||||
thermal_zone_unbind_cooling_device(
|
||||
thermal, trip, cdev);
|
||||
|
||||
if (result)
|
||||
goto failed;
|
||||
}
|
||||
@ -735,22 +734,24 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
|
||||
for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
|
||||
if (!tz->trips.active[i].flags.valid)
|
||||
break;
|
||||
|
||||
trip++;
|
||||
for (j = 0;
|
||||
j < tz->trips.active[i].devices.count;
|
||||
j++) {
|
||||
for (j = 0; j < tz->trips.active[i].devices.count; j++) {
|
||||
handle = tz->trips.active[i].devices.handles[j];
|
||||
dev = acpi_fetch_acpi_dev(handle);
|
||||
if (dev != device)
|
||||
continue;
|
||||
|
||||
if (bind)
|
||||
result = thermal_zone_bind_cooling_device
|
||||
(thermal, trip, cdev,
|
||||
THERMAL_NO_LIMIT, THERMAL_NO_LIMIT,
|
||||
result = thermal_zone_bind_cooling_device(
|
||||
thermal, trip, cdev,
|
||||
THERMAL_NO_LIMIT,
|
||||
THERMAL_NO_LIMIT,
|
||||
THERMAL_WEIGHT_DEFAULT);
|
||||
else
|
||||
result = thermal_zone_unbind_cooling_device
|
||||
(thermal, trip, cdev);
|
||||
result = thermal_zone_unbind_cooling_device(
|
||||
thermal, trip, cdev);
|
||||
|
||||
if (result)
|
||||
goto failed;
|
||||
}
|
||||
@ -802,12 +803,11 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
|
||||
if (tz->trips.passive.flags.valid)
|
||||
trips++;
|
||||
|
||||
for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
|
||||
tz->trips.active[i].flags.valid; i++, trips++);
|
||||
for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE && tz->trips.active[i].flags.valid;
|
||||
i++, trips++);
|
||||
|
||||
if (tz->trips.passive.flags.valid)
|
||||
tz->thermal_zone =
|
||||
thermal_zone_device_register("acpitz", trips, 0, tz,
|
||||
tz->thermal_zone = thermal_zone_device_register("acpitz", trips, 0, tz,
|
||||
&acpi_thermal_zone_ops, NULL,
|
||||
tz->trips.passive.tsp * 100,
|
||||
tz->polling_frequency * 100);
|
||||
@ -816,6 +816,7 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
|
||||
thermal_zone_device_register("acpitz", trips, 0, tz,
|
||||
&acpi_thermal_zone_ops, NULL,
|
||||
0, tz->polling_frequency * 100);
|
||||
|
||||
if (IS_ERR(tz->thermal_zone))
|
||||
return -ENODEV;
|
||||
|
||||
@ -881,7 +882,6 @@ static void acpi_thermal_notify(struct acpi_device *device, u32 event)
|
||||
{
|
||||
struct acpi_thermal *tz = acpi_driver_data(device);
|
||||
|
||||
|
||||
if (!tz)
|
||||
return;
|
||||
|
||||
@ -942,8 +942,7 @@ static void acpi_thermal_aml_dependency_fix(struct acpi_thermal *tz)
|
||||
|
||||
static int acpi_thermal_get_info(struct acpi_thermal *tz)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
int result;
|
||||
|
||||
if (!tz)
|
||||
return -EINVAL;
|
||||
@ -1020,9 +1019,8 @@ static void acpi_thermal_check_fn(struct work_struct *work)
|
||||
|
||||
static int acpi_thermal_add(struct acpi_device *device)
|
||||
{
|
||||
int result = 0;
|
||||
struct acpi_thermal *tz = NULL;
|
||||
|
||||
struct acpi_thermal *tz;
|
||||
int result;
|
||||
|
||||
if (!device)
|
||||
return -EINVAL;
|
||||
@ -1063,7 +1061,7 @@ end:
|
||||
|
||||
static int acpi_thermal_remove(struct acpi_device *device)
|
||||
{
|
||||
struct acpi_thermal *tz = NULL;
|
||||
struct acpi_thermal *tz;
|
||||
|
||||
if (!device || !acpi_driver_data(device))
|
||||
return -EINVAL;
|
||||
@ -1099,6 +1097,7 @@ static int acpi_thermal_resume(struct device *dev)
|
||||
for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
|
||||
if (!tz->trips.active[i].flags.valid)
|
||||
break;
|
||||
|
||||
tz->trips.active[i].flags.enabled = 1;
|
||||
for (j = 0; j < tz->trips.active[i].devices.count; j++) {
|
||||
result = acpi_bus_update_power(
|
||||
@ -1119,7 +1118,6 @@ static int acpi_thermal_resume(struct device *dev)
|
||||
#endif
|
||||
|
||||
static int thermal_act(const struct dmi_system_id *d) {
|
||||
|
||||
if (act == 0) {
|
||||
pr_notice("%s detected: disabling all active thermal trip points\n",
|
||||
d->ident);
|
||||
@ -1128,14 +1126,12 @@ static int thermal_act(const struct dmi_system_id *d) {
|
||||
return 0;
|
||||
}
|
||||
static int thermal_nocrt(const struct dmi_system_id *d) {
|
||||
|
||||
pr_notice("%s detected: disabling all critical thermal trip point actions.\n",
|
||||
d->ident);
|
||||
nocrt = 1;
|
||||
return 0;
|
||||
}
|
||||
static int thermal_tzp(const struct dmi_system_id *d) {
|
||||
|
||||
if (tzp == 0) {
|
||||
pr_notice("%s detected: enabling thermal zone polling\n",
|
||||
d->ident);
|
||||
@ -1144,7 +1140,6 @@ static int thermal_tzp(const struct dmi_system_id *d) {
|
||||
return 0;
|
||||
}
|
||||
static int thermal_psv(const struct dmi_system_id *d) {
|
||||
|
||||
if (psv == 0) {
|
||||
pr_notice("%s detected: disabling all passive thermal trip points\n",
|
||||
d->ident);
|
||||
@ -1195,7 +1190,7 @@ static const struct dmi_system_id thermal_dmi_table[] __initconst = {
|
||||
|
||||
static int __init acpi_thermal_init(void)
|
||||
{
|
||||
int result = 0;
|
||||
int result;
|
||||
|
||||
dmi_check_system(thermal_dmi_table);
|
||||
|
||||
@ -1222,8 +1217,6 @@ static void __exit acpi_thermal_exit(void)
|
||||
{
|
||||
acpi_bus_unregister_driver(&acpi_thermal_driver);
|
||||
destroy_workqueue(acpi_thermal_pm_queue);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
module_init(acpi_thermal_init);
|
||||
|
@ -754,6 +754,7 @@ static int acpi_populate_gpio_lookup(struct acpi_resource *ares, void *data)
|
||||
lookup->info.pin_config = agpio->pin_config;
|
||||
lookup->info.debounce = agpio->debounce_timeout;
|
||||
lookup->info.gpioint = gpioint;
|
||||
lookup->info.wake_capable = agpio->wake_capable == ACPI_WAKE_CAPABLE;
|
||||
|
||||
/*
|
||||
* Polarity and triggering are only specified for GpioInt
|
||||
@ -1000,10 +1001,11 @@ struct gpio_desc *acpi_node_get_gpiod(struct fwnode_handle *fwnode,
|
||||
}
|
||||
|
||||
/**
|
||||
* acpi_dev_gpio_irq_get_by() - Find GpioInt and translate it to Linux IRQ number
|
||||
* acpi_dev_gpio_irq_wake_get_by() - Find GpioInt and translate it to Linux IRQ number
|
||||
* @adev: pointer to a ACPI device to get IRQ from
|
||||
* @name: optional name of GpioInt resource
|
||||
* @index: index of GpioInt resource (starting from %0)
|
||||
* @wake_capable: Set to true if the IRQ is wake capable
|
||||
*
|
||||
* If the device has one or more GpioInt resources, this function can be
|
||||
* used to translate from the GPIO offset in the resource to the Linux IRQ
|
||||
@ -1015,9 +1017,13 @@ struct gpio_desc *acpi_node_get_gpiod(struct fwnode_handle *fwnode,
|
||||
* The function takes optional @name parameter. If the resource has a property
|
||||
* name, then only those will be taken into account.
|
||||
*
|
||||
* The GPIO is considered wake capable if the GpioInt resource specifies
|
||||
* SharedAndWake or ExclusiveAndWake.
|
||||
*
|
||||
* Return: Linux IRQ number (> %0) on success, negative errno on failure.
|
||||
*/
|
||||
int acpi_dev_gpio_irq_get_by(struct acpi_device *adev, const char *name, int index)
|
||||
int acpi_dev_gpio_irq_wake_get_by(struct acpi_device *adev, const char *name, int index,
|
||||
bool *wake_capable)
|
||||
{
|
||||
int idx, i;
|
||||
unsigned int irq_flags;
|
||||
@ -1074,13 +1080,16 @@ int acpi_dev_gpio_irq_get_by(struct acpi_device *adev, const char *name, int ind
|
||||
dev_dbg(&adev->dev, "IRQ %d already in use\n", irq);
|
||||
}
|
||||
|
||||
if (wake_capable)
|
||||
*wake_capable = info.wake_capable;
|
||||
|
||||
return irq;
|
||||
}
|
||||
|
||||
}
|
||||
return -ENOENT;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_dev_gpio_irq_get_by);
|
||||
EXPORT_SYMBOL_GPL(acpi_dev_gpio_irq_wake_get_by);
|
||||
|
||||
static acpi_status
|
||||
acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address,
|
||||
|
@ -18,6 +18,7 @@ struct acpi_device;
|
||||
* @pin_config: pin bias as provided by ACPI
|
||||
* @polarity: interrupt polarity as provided by ACPI
|
||||
* @triggering: triggering type as provided by ACPI
|
||||
* @wake_capable: wake capability as provided by ACPI
|
||||
* @debounce: debounce timeout as provided by ACPI
|
||||
* @quirks: Linux specific quirks as provided by struct acpi_gpio_mapping
|
||||
*/
|
||||
@ -28,6 +29,7 @@ struct acpi_gpio_info {
|
||||
int pin_config;
|
||||
int polarity;
|
||||
int triggering;
|
||||
bool wake_capable;
|
||||
unsigned int debounce;
|
||||
unsigned int quirks;
|
||||
};
|
||||
|
@ -137,6 +137,11 @@ static const struct acpi_device_id i2c_acpi_ignored_device_ids[] = {
|
||||
{}
|
||||
};
|
||||
|
||||
struct i2c_acpi_irq_context {
|
||||
int irq;
|
||||
bool wake_capable;
|
||||
};
|
||||
|
||||
static int i2c_acpi_do_lookup(struct acpi_device *adev,
|
||||
struct i2c_acpi_lookup *lookup)
|
||||
{
|
||||
@ -168,13 +173,19 @@ static int i2c_acpi_do_lookup(struct acpi_device *adev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i2c_acpi_add_resource(struct acpi_resource *ares, void *data)
|
||||
static int i2c_acpi_add_irq_resource(struct acpi_resource *ares, void *data)
|
||||
{
|
||||
int *irq = data;
|
||||
struct i2c_acpi_irq_context *irq_ctx = data;
|
||||
struct resource r;
|
||||
|
||||
if (*irq <= 0 && acpi_dev_resource_interrupt(ares, 0, &r))
|
||||
*irq = i2c_dev_irq_from_resources(&r, 1);
|
||||
if (irq_ctx->irq > 0)
|
||||
return 1;
|
||||
|
||||
if (!acpi_dev_resource_interrupt(ares, 0, &r))
|
||||
return 1;
|
||||
|
||||
irq_ctx->irq = i2c_dev_irq_from_resources(&r, 1);
|
||||
irq_ctx->wake_capable = r.flags & IORESOURCE_IRQ_WAKECAPABLE;
|
||||
|
||||
return 1; /* No need to add resource to the list */
|
||||
}
|
||||
@ -182,31 +193,40 @@ static int i2c_acpi_add_resource(struct acpi_resource *ares, void *data)
|
||||
/**
|
||||
* i2c_acpi_get_irq - get device IRQ number from ACPI
|
||||
* @client: Pointer to the I2C client device
|
||||
* @wake_capable: Set to true if the IRQ is wake capable
|
||||
*
|
||||
* Find the IRQ number used by a specific client device.
|
||||
*
|
||||
* Return: The IRQ number or an error code.
|
||||
*/
|
||||
int i2c_acpi_get_irq(struct i2c_client *client)
|
||||
int i2c_acpi_get_irq(struct i2c_client *client, bool *wake_capable)
|
||||
{
|
||||
struct acpi_device *adev = ACPI_COMPANION(&client->dev);
|
||||
struct list_head resource_list;
|
||||
int irq = -ENOENT;
|
||||
struct i2c_acpi_irq_context irq_ctx = {
|
||||
.irq = -ENOENT,
|
||||
};
|
||||
int ret;
|
||||
|
||||
INIT_LIST_HEAD(&resource_list);
|
||||
|
||||
ret = acpi_dev_get_resources(adev, &resource_list,
|
||||
i2c_acpi_add_resource, &irq);
|
||||
i2c_acpi_add_irq_resource, &irq_ctx);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
acpi_dev_free_resource_list(&resource_list);
|
||||
|
||||
if (irq == -ENOENT)
|
||||
irq = acpi_dev_gpio_irq_get(adev, 0);
|
||||
if (irq_ctx.irq == -ENOENT)
|
||||
irq_ctx.irq = acpi_dev_gpio_irq_wake_get(adev, 0, &irq_ctx.wake_capable);
|
||||
|
||||
return irq;
|
||||
if (irq_ctx.irq < 0)
|
||||
return irq_ctx.irq;
|
||||
|
||||
if (wake_capable)
|
||||
*wake_capable = irq_ctx.wake_capable;
|
||||
|
||||
return irq_ctx.irq;
|
||||
}
|
||||
|
||||
static int i2c_acpi_get_info(struct acpi_device *adev,
|
||||
|
@ -487,7 +487,11 @@ static int i2c_device_probe(struct device *dev)
|
||||
if (irq == -EINVAL || irq == -ENODATA)
|
||||
irq = of_irq_get(dev->of_node, 0);
|
||||
} else if (ACPI_COMPANION(dev)) {
|
||||
irq = i2c_acpi_get_irq(client);
|
||||
bool wake_capable;
|
||||
|
||||
irq = i2c_acpi_get_irq(client, &wake_capable);
|
||||
if (irq > 0 && wake_capable)
|
||||
client->flags |= I2C_CLIENT_WAKE;
|
||||
}
|
||||
if (irq == -EPROBE_DEFER) {
|
||||
status = irq;
|
||||
|
@ -61,11 +61,11 @@ static inline int __i2c_check_suspended(struct i2c_adapter *adap)
|
||||
#ifdef CONFIG_ACPI
|
||||
void i2c_acpi_register_devices(struct i2c_adapter *adap);
|
||||
|
||||
int i2c_acpi_get_irq(struct i2c_client *client);
|
||||
int i2c_acpi_get_irq(struct i2c_client *client, bool *wake_capable);
|
||||
#else /* CONFIG_ACPI */
|
||||
static inline void i2c_acpi_register_devices(struct i2c_adapter *adap) { }
|
||||
|
||||
static inline int i2c_acpi_get_irq(struct i2c_client *client)
|
||||
static inline int i2c_acpi_get_irq(struct i2c_client *client, bool *wake_capable)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -128,15 +128,15 @@ skl_int3472_fill_clk_pdata(struct device *dev, struct tps68470_clk_platform_data
|
||||
for_each_acpi_consumer_dev(adev, consumer) {
|
||||
sensor_name = devm_kasprintf(dev, GFP_KERNEL, I2C_DEV_NAME_FORMAT,
|
||||
acpi_dev_name(consumer));
|
||||
if (!sensor_name)
|
||||
if (!sensor_name) {
|
||||
acpi_dev_put(consumer);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
(*clk_pdata)->consumers[i].consumer_dev_name = sensor_name;
|
||||
i++;
|
||||
}
|
||||
|
||||
acpi_dev_put(consumer);
|
||||
|
||||
return n_consumers;
|
||||
}
|
||||
|
||||
|
@ -206,7 +206,8 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
|
||||
if (i >= 0) {
|
||||
flags = acpi_dev_irq_flags(gpio->triggering,
|
||||
gpio->polarity,
|
||||
gpio->shareable);
|
||||
gpio->shareable,
|
||||
gpio->wake_capable);
|
||||
} else {
|
||||
flags = IORESOURCE_DISABLED;
|
||||
}
|
||||
@ -315,7 +316,7 @@ static __init void pnpacpi_parse_irq_option(struct pnp_dev *dev,
|
||||
if (p->interrupts[i])
|
||||
__set_bit(p->interrupts[i], map.bits);
|
||||
|
||||
flags = acpi_dev_irq_flags(p->triggering, p->polarity, p->shareable);
|
||||
flags = acpi_dev_irq_flags(p->triggering, p->polarity, p->shareable, p->wake_capable);
|
||||
pnp_register_irq_resource(dev, option_flags, &map, flags);
|
||||
}
|
||||
|
||||
@ -339,7 +340,7 @@ static __init void pnpacpi_parse_ext_irq_option(struct pnp_dev *dev,
|
||||
}
|
||||
}
|
||||
|
||||
flags = acpi_dev_irq_flags(p->triggering, p->polarity, p->shareable);
|
||||
flags = acpi_dev_irq_flags(p->triggering, p->polarity, p->shareable, p->wake_capable);
|
||||
pnp_register_irq_resource(dev, option_flags, &map, flags);
|
||||
}
|
||||
|
||||
|
@ -498,7 +498,7 @@ bool acpi_dev_resource_address_space(struct acpi_resource *ares,
|
||||
struct resource_win *win);
|
||||
bool acpi_dev_resource_ext_address_space(struct acpi_resource *ares,
|
||||
struct resource_win *win);
|
||||
unsigned long acpi_dev_irq_flags(u8 triggering, u8 polarity, u8 shareable);
|
||||
unsigned long acpi_dev_irq_flags(u8 triggering, u8 polarity, u8 shareable, u8 wake_capable);
|
||||
unsigned int acpi_dev_get_irq_type(int triggering, int polarity);
|
||||
bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index,
|
||||
struct resource *res);
|
||||
@ -1211,7 +1211,8 @@ bool acpi_gpio_get_irq_resource(struct acpi_resource *ares,
|
||||
struct acpi_resource_gpio **agpio);
|
||||
bool acpi_gpio_get_io_resource(struct acpi_resource *ares,
|
||||
struct acpi_resource_gpio **agpio);
|
||||
int acpi_dev_gpio_irq_get_by(struct acpi_device *adev, const char *name, int index);
|
||||
int acpi_dev_gpio_irq_wake_get_by(struct acpi_device *adev, const char *name, int index,
|
||||
bool *wake_capable);
|
||||
#else
|
||||
static inline bool acpi_gpio_get_irq_resource(struct acpi_resource *ares,
|
||||
struct acpi_resource_gpio **agpio)
|
||||
@ -1223,16 +1224,28 @@ static inline bool acpi_gpio_get_io_resource(struct acpi_resource *ares,
|
||||
{
|
||||
return false;
|
||||
}
|
||||
static inline int acpi_dev_gpio_irq_get_by(struct acpi_device *adev,
|
||||
const char *name, int index)
|
||||
static inline int acpi_dev_gpio_irq_wake_get_by(struct acpi_device *adev, const char *name,
|
||||
int index, bool *wake_capable)
|
||||
{
|
||||
return -ENXIO;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline int acpi_dev_gpio_irq_wake_get(struct acpi_device *adev, int index,
|
||||
bool *wake_capable)
|
||||
{
|
||||
return acpi_dev_gpio_irq_wake_get_by(adev, NULL, index, wake_capable);
|
||||
}
|
||||
|
||||
static inline int acpi_dev_gpio_irq_get_by(struct acpi_device *adev, const char *name,
|
||||
int index)
|
||||
{
|
||||
return acpi_dev_gpio_irq_wake_get_by(adev, name, index, NULL);
|
||||
}
|
||||
|
||||
static inline int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index)
|
||||
{
|
||||
return acpi_dev_gpio_irq_get_by(adev, NULL, index);
|
||||
return acpi_dev_gpio_irq_wake_get_by(adev, NULL, index, NULL);
|
||||
}
|
||||
|
||||
/* Device properties */
|
||||
|
@ -80,6 +80,7 @@ struct resource {
|
||||
#define IORESOURCE_IRQ_LOWLEVEL (1<<3)
|
||||
#define IORESOURCE_IRQ_SHAREABLE (1<<4)
|
||||
#define IORESOURCE_IRQ_OPTIONAL (1<<5)
|
||||
#define IORESOURCE_IRQ_WAKECAPABLE (1<<6)
|
||||
|
||||
/* PnP DMA specific bits (IORESOURCE_BITS) */
|
||||
#define IORESOURCE_DMA_TYPE_MASK (3<<0)
|
||||
|
@ -105,6 +105,14 @@ enum sys_off_mode {
|
||||
*/
|
||||
SYS_OFF_MODE_POWER_OFF,
|
||||
|
||||
/**
|
||||
* @SYS_OFF_MODE_RESTART_PREPARE:
|
||||
*
|
||||
* Handlers prepare system to be restarted. Handlers are
|
||||
* allowed to sleep.
|
||||
*/
|
||||
SYS_OFF_MODE_RESTART_PREPARE,
|
||||
|
||||
/**
|
||||
* @SYS_OFF_MODE_RESTART:
|
||||
*
|
||||
|
@ -243,6 +243,17 @@ void migrate_to_reboot_cpu(void)
|
||||
set_cpus_allowed_ptr(current, cpumask_of(cpu));
|
||||
}
|
||||
|
||||
/*
|
||||
* Notifier list for kernel code which wants to be called
|
||||
* to prepare system for restart.
|
||||
*/
|
||||
static BLOCKING_NOTIFIER_HEAD(restart_prep_handler_list);
|
||||
|
||||
static void do_kernel_restart_prepare(void)
|
||||
{
|
||||
blocking_notifier_call_chain(&restart_prep_handler_list, 0, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* kernel_restart - reboot the system
|
||||
* @cmd: pointer to buffer containing command to execute for restart
|
||||
@ -254,6 +265,7 @@ void migrate_to_reboot_cpu(void)
|
||||
void kernel_restart(char *cmd)
|
||||
{
|
||||
kernel_restart_prepare(cmd);
|
||||
do_kernel_restart_prepare();
|
||||
migrate_to_reboot_cpu();
|
||||
syscore_shutdown();
|
||||
if (!cmd)
|
||||
@ -396,6 +408,11 @@ register_sys_off_handler(enum sys_off_mode mode,
|
||||
handler->list = &power_off_handler_list;
|
||||
break;
|
||||
|
||||
case SYS_OFF_MODE_RESTART_PREPARE:
|
||||
handler->list = &restart_prep_handler_list;
|
||||
handler->blocking = true;
|
||||
break;
|
||||
|
||||
case SYS_OFF_MODE_RESTART:
|
||||
handler->list = &restart_handler_list;
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user