Commit 056a8154 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

Merge branches 'acpi-apei', 'acpi-wakeup', 'acpi-reboot' and 'acpi-thermal'

Merge additional APEI changes, ACPI updates related to device wakeup and
system restart and ACPI thermal driver cleanups for 6.1-rc1:

 - Fix a memory leak in APEI by avoiding to add do not add 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).

* acpi-apei:
  ACPI: APEI: do not add task_work to kernel thread to avoid memory leak

* acpi-wakeup:
  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

* acpi-reboot:
  PM: ACPI: reboot: Reinstate S5 for reboot
  kernel/reboot: Add SYS_OFF_MODE_RESTART_PREPARE mode

* acpi-thermal:
  ACPI: thermal: Drop some redundant code
  ACPI: thermal: Drop redundant parens from expressions
  ACPI: thermal: Use white space more consistently
...@@ -985,7 +985,7 @@ static void ghes_proc_in_irq(struct irq_work *irq_work) ...@@ -985,7 +985,7 @@ static void ghes_proc_in_irq(struct irq_work *irq_work)
ghes_estatus_cache_add(generic, estatus); 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.func = ghes_kick_task_work;
estatus_node->task_work_cpu = smp_processor_id(); estatus_node->task_work_cpu = smp_processor_id();
ret = task_work_add(current, &estatus_node->task_work, 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, ...@@ -687,7 +687,22 @@ static int acpi_dev_pm_get_state(struct device *dev, struct acpi_device *adev,
d_min = ret; d_min = ret;
wakeup = device_may_wakeup(dev) && adev->wakeup.flags.valid wakeup = device_may_wakeup(dev) && adev->wakeup.flags.valid
&& adev->wakeup.sleep_state >= target_state; && 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 { } else {
/* ACPI GPE is specified in _PRW. */
wakeup = adev->wakeup.flags.valid; wakeup = adev->wakeup.flags.valid;
} }
......
...@@ -147,6 +147,7 @@ struct acpi_irq_parse_one_ctx { ...@@ -147,6 +147,7 @@ struct acpi_irq_parse_one_ctx {
* @polarity: polarity attributes of hwirq * @polarity: polarity attributes of hwirq
* @polarity: polarity attributes of hwirq * @polarity: polarity attributes of hwirq
* @shareable: shareable 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 * @ctx: acpi_irq_parse_one_ctx updated by this function
* *
* Description: * Description:
...@@ -156,12 +157,13 @@ struct acpi_irq_parse_one_ctx { ...@@ -156,12 +157,13 @@ struct acpi_irq_parse_one_ctx {
static inline void acpi_irq_parse_one_match(struct fwnode_handle *fwnode, static inline void acpi_irq_parse_one_match(struct fwnode_handle *fwnode,
u32 hwirq, u8 triggering, u32 hwirq, u8 triggering,
u8 polarity, u8 shareable, u8 polarity, u8 shareable,
u8 wake_capable,
struct acpi_irq_parse_one_ctx *ctx) struct acpi_irq_parse_one_ctx *ctx)
{ {
if (!fwnode) if (!fwnode)
return; return;
ctx->rc = 0; 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->fwnode = fwnode;
ctx->fwspec->param[0] = hwirq; ctx->fwspec->param[0] = hwirq;
ctx->fwspec->param[1] = acpi_dev_get_irq_type(triggering, polarity); 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, ...@@ -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]); fwnode = acpi_get_gsi_domain_id(irq->interrupts[ctx->index]);
acpi_irq_parse_one_match(fwnode, irq->interrupts[ctx->index], acpi_irq_parse_one_match(fwnode, irq->interrupts[ctx->index],
irq->triggering, irq->polarity, irq->triggering, irq->polarity,
irq->shareable, ctx); irq->shareable, irq->wake_capable, ctx);
return AE_CTRL_TERMINATE; return AE_CTRL_TERMINATE;
case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
eirq = &ares->data.extended_irq; eirq = &ares->data.extended_irq;
...@@ -218,7 +220,7 @@ static acpi_status acpi_irq_parse_one_cb(struct acpi_resource *ares, ...@@ -218,7 +220,7 @@ static acpi_status acpi_irq_parse_one_cb(struct acpi_resource *ares,
eirq->interrupts[ctx->index]); eirq->interrupts[ctx->index]);
acpi_irq_parse_one_match(fwnode, eirq->interrupts[ctx->index], acpi_irq_parse_one_match(fwnode, eirq->interrupts[ctx->index],
eirq->triggering, eirq->polarity, eirq->triggering, eirq->polarity,
eirq->shareable, ctx); eirq->shareable, eirq->wake_capable, ctx);
return AE_CTRL_TERMINATE; return AE_CTRL_TERMINATE;
} }
......
...@@ -336,8 +336,9 @@ EXPORT_SYMBOL_GPL(acpi_dev_resource_ext_address_space); ...@@ -336,8 +336,9 @@ EXPORT_SYMBOL_GPL(acpi_dev_resource_ext_address_space);
* @triggering: Triggering type as provided by ACPI. * @triggering: Triggering type as provided by ACPI.
* @polarity: Interrupt polarity as provided by ACPI. * @polarity: Interrupt polarity as provided by ACPI.
* @shareable: Whether or not the interrupt is shareable. * @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; unsigned long flags;
...@@ -351,6 +352,9 @@ unsigned long acpi_dev_irq_flags(u8 triggering, u8 polarity, u8 shareable) ...@@ -351,6 +352,9 @@ unsigned long acpi_dev_irq_flags(u8 triggering, u8 polarity, u8 shareable)
if (shareable == ACPI_SHARED) if (shareable == ACPI_SHARED)
flags |= IORESOURCE_IRQ_SHAREABLE; flags |= IORESOURCE_IRQ_SHAREABLE;
if (wake_capable == ACPI_WAKE_CAPABLE)
flags |= IORESOURCE_IRQ_WAKECAPABLE;
return flags | IORESOURCE_IRQ; return flags | IORESOURCE_IRQ;
} }
EXPORT_SYMBOL_GPL(acpi_dev_irq_flags); EXPORT_SYMBOL_GPL(acpi_dev_irq_flags);
...@@ -468,7 +472,7 @@ static bool acpi_dev_irq_override(u32 gsi, u8 triggering, u8 polarity, ...@@ -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, static void acpi_dev_get_irqresource(struct resource *res, u32 gsi,
u8 triggering, u8 polarity, u8 shareable, u8 triggering, u8 polarity, u8 shareable,
bool check_override) u8 wake_capable, bool check_override)
{ {
int irq, p, t; int irq, p, t;
...@@ -501,7 +505,7 @@ static void acpi_dev_get_irqresource(struct resource *res, u32 gsi, ...@@ -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); irq = acpi_register_gsi(NULL, gsi, triggering, polarity);
if (irq >= 0) { if (irq >= 0) {
res->start = irq; res->start = irq;
...@@ -549,7 +553,8 @@ bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index, ...@@ -549,7 +553,8 @@ bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index,
} }
acpi_dev_get_irqresource(res, irq->interrupts[index], acpi_dev_get_irqresource(res, irq->interrupts[index],
irq->triggering, irq->polarity, irq->triggering, irq->polarity,
irq->shareable, true); irq->shareable, irq->wake_capable,
true);
break; break;
case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
ext_irq = &ares->data.extended_irq; ext_irq = &ares->data.extended_irq;
...@@ -560,7 +565,8 @@ bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index, ...@@ -560,7 +565,8 @@ bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index,
if (is_gsi(ext_irq)) if (is_gsi(ext_irq))
acpi_dev_get_irqresource(res, ext_irq->interrupts[index], acpi_dev_get_irqresource(res, ext_irq->interrupts[index],
ext_irq->triggering, ext_irq->polarity, ext_irq->triggering, ext_irq->polarity,
ext_irq->shareable, false); ext_irq->shareable, ext_irq->wake_capable,
false);
else else
irqresource_disabled(res, 0); irqresource_disabled(res, 0);
break; break;
......
...@@ -1088,6 +1088,14 @@ int __init acpi_sleep_init(void) ...@@ -1088,6 +1088,14 @@ int __init acpi_sleep_init(void)
register_sys_off_handler(SYS_OFF_MODE_POWER_OFF, register_sys_off_handler(SYS_OFF_MODE_POWER_OFF,
SYS_OFF_PRIO_FIRMWARE, SYS_OFF_PRIO_FIRMWARE,
acpi_power_off, NULL); 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 { } else {
acpi_no_s5 = true; acpi_no_s5 = true;
} }
......
This diff is collapsed.
...@@ -741,6 +741,7 @@ static int acpi_populate_gpio_lookup(struct acpi_resource *ares, void *data) ...@@ -741,6 +741,7 @@ static int acpi_populate_gpio_lookup(struct acpi_resource *ares, void *data)
lookup->info.pin_config = agpio->pin_config; lookup->info.pin_config = agpio->pin_config;
lookup->info.debounce = agpio->debounce_timeout; lookup->info.debounce = agpio->debounce_timeout;
lookup->info.gpioint = gpioint; lookup->info.gpioint = gpioint;
lookup->info.wake_capable = agpio->wake_capable == ACPI_WAKE_CAPABLE;
/* /*
* Polarity and triggering are only specified for GpioInt * Polarity and triggering are only specified for GpioInt
...@@ -987,10 +988,11 @@ struct gpio_desc *acpi_node_get_gpiod(struct fwnode_handle *fwnode, ...@@ -987,10 +988,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 * @adev: pointer to a ACPI device to get IRQ from
* @name: optional name of GpioInt resource * @name: optional name of GpioInt resource
* @index: index of GpioInt resource (starting from %0) * @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 * 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 * used to translate from the GPIO offset in the resource to the Linux IRQ
...@@ -1002,9 +1004,13 @@ struct gpio_desc *acpi_node_get_gpiod(struct fwnode_handle *fwnode, ...@@ -1002,9 +1004,13 @@ struct gpio_desc *acpi_node_get_gpiod(struct fwnode_handle *fwnode,
* The function takes optional @name parameter. If the resource has a property * The function takes optional @name parameter. If the resource has a property
* name, then only those will be taken into account. * 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. * 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; int idx, i;
unsigned int irq_flags; unsigned int irq_flags;
...@@ -1061,13 +1067,16 @@ int acpi_dev_gpio_irq_get_by(struct acpi_device *adev, const char *name, int ind ...@@ -1061,13 +1067,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); dev_dbg(&adev->dev, "IRQ %d already in use\n", irq);
} }
if (wake_capable)
*wake_capable = info.wake_capable;
return irq; return irq;
} }
} }
return -ENOENT; return -ENOENT;
} }
EXPORT_SYMBOL_GPL(acpi_dev_gpio_irq_get_by); EXPORT_SYMBOL_GPL(acpi_dev_gpio_irq_wake_get_by);
static acpi_status static acpi_status
acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address, acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address,
......
...@@ -18,6 +18,7 @@ struct acpi_device; ...@@ -18,6 +18,7 @@ struct acpi_device;
* @pin_config: pin bias as provided by ACPI * @pin_config: pin bias as provided by ACPI
* @polarity: interrupt polarity as provided by ACPI * @polarity: interrupt polarity as provided by ACPI
* @triggering: triggering type 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 * @debounce: debounce timeout as provided by ACPI
* @quirks: Linux specific quirks as provided by struct acpi_gpio_mapping * @quirks: Linux specific quirks as provided by struct acpi_gpio_mapping
*/ */
...@@ -28,6 +29,7 @@ struct acpi_gpio_info { ...@@ -28,6 +29,7 @@ struct acpi_gpio_info {
int pin_config; int pin_config;
int polarity; int polarity;
int triggering; int triggering;
bool wake_capable;
unsigned int debounce; unsigned int debounce;
unsigned int quirks; unsigned int quirks;
}; };
......
...@@ -137,6 +137,11 @@ static const struct acpi_device_id i2c_acpi_ignored_device_ids[] = { ...@@ -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, static int i2c_acpi_do_lookup(struct acpi_device *adev,
struct i2c_acpi_lookup *lookup) struct i2c_acpi_lookup *lookup)
{ {
...@@ -168,13 +173,19 @@ static int i2c_acpi_do_lookup(struct acpi_device *adev, ...@@ -168,13 +173,19 @@ static int i2c_acpi_do_lookup(struct acpi_device *adev,
return 0; 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; struct resource r;
if (*irq <= 0 && acpi_dev_resource_interrupt(ares, 0, &r)) if (irq_ctx->irq > 0)
*irq = i2c_dev_irq_from_resources(&r, 1); 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 */ 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) ...@@ -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 * i2c_acpi_get_irq - get device IRQ number from ACPI
* @client: Pointer to the I2C client device * @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. * Find the IRQ number used by a specific client device.
* *
* Return: The IRQ number or an error code. * 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 acpi_device *adev = ACPI_COMPANION(&client->dev);
struct list_head resource_list; struct list_head resource_list;
int irq = -ENOENT; struct i2c_acpi_irq_context irq_ctx = {
.irq = -ENOENT,
};
int ret; int ret;
INIT_LIST_HEAD(&resource_list); INIT_LIST_HEAD(&resource_list);
ret = acpi_dev_get_resources(adev, &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) if (ret < 0)
return ret; return ret;
acpi_dev_free_resource_list(&resource_list); acpi_dev_free_resource_list(&resource_list);
if (irq == -ENOENT) if (irq_ctx.irq == -ENOENT)
irq = acpi_dev_gpio_irq_get(adev, 0); irq_ctx.irq = acpi_dev_gpio_irq_wake_get(adev, 0, &irq_ctx.wake_capable);
if (irq_ctx.irq < 0)
return irq_ctx.irq;
if (wake_capable)
*wake_capable = irq_ctx.wake_capable;
return irq; return irq_ctx.irq;
} }
static int i2c_acpi_get_info(struct acpi_device *adev, static int i2c_acpi_get_info(struct acpi_device *adev,
......
...@@ -487,7 +487,11 @@ static int i2c_device_probe(struct device *dev) ...@@ -487,7 +487,11 @@ static int i2c_device_probe(struct device *dev)
if (irq == -EINVAL || irq == -ENODATA) if (irq == -EINVAL || irq == -ENODATA)
irq = of_irq_get(dev->of_node, 0); irq = of_irq_get(dev->of_node, 0);
} else if (ACPI_COMPANION(dev)) { } 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) { if (irq == -EPROBE_DEFER) {
status = irq; status = irq;
......
...@@ -61,11 +61,11 @@ static inline int __i2c_check_suspended(struct i2c_adapter *adap) ...@@ -61,11 +61,11 @@ static inline int __i2c_check_suspended(struct i2c_adapter *adap)
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
void i2c_acpi_register_devices(struct i2c_adapter *adap); 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 */ #else /* CONFIG_ACPI */
static inline void i2c_acpi_register_devices(struct i2c_adapter *adap) { } 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; return 0;
} }
......
...@@ -206,7 +206,8 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, ...@@ -206,7 +206,8 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
if (i >= 0) { if (i >= 0) {
flags = acpi_dev_irq_flags(gpio->triggering, flags = acpi_dev_irq_flags(gpio->triggering,
gpio->polarity, gpio->polarity,
gpio->shareable); gpio->shareable,
gpio->wake_capable);
} else { } else {
flags = IORESOURCE_DISABLED; flags = IORESOURCE_DISABLED;
} }
...@@ -315,7 +316,7 @@ static __init void pnpacpi_parse_irq_option(struct pnp_dev *dev, ...@@ -315,7 +316,7 @@ static __init void pnpacpi_parse_irq_option(struct pnp_dev *dev,
if (p->interrupts[i]) if (p->interrupts[i])
__set_bit(p->interrupts[i], map.bits); __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); 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, ...@@ -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); pnp_register_irq_resource(dev, option_flags, &map, flags);
} }
......
...@@ -498,7 +498,7 @@ bool acpi_dev_resource_address_space(struct acpi_resource *ares, ...@@ -498,7 +498,7 @@ bool acpi_dev_resource_address_space(struct acpi_resource *ares,
struct resource_win *win); struct resource_win *win);
bool acpi_dev_resource_ext_address_space(struct acpi_resource *ares, bool acpi_dev_resource_ext_address_space(struct acpi_resource *ares,
struct resource_win *win); 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); unsigned int acpi_dev_get_irq_type(int triggering, int polarity);
bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index, bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index,
struct resource *res); struct resource *res);
...@@ -1210,7 +1210,8 @@ bool acpi_gpio_get_irq_resource(struct acpi_resource *ares, ...@@ -1210,7 +1210,8 @@ bool acpi_gpio_get_irq_resource(struct acpi_resource *ares,
struct acpi_resource_gpio **agpio); struct acpi_resource_gpio **agpio);
bool acpi_gpio_get_io_resource(struct acpi_resource *ares, bool acpi_gpio_get_io_resource(struct acpi_resource *ares,
struct acpi_resource_gpio **agpio); 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 #else
static inline bool acpi_gpio_get_irq_resource(struct acpi_resource *ares, static inline bool acpi_gpio_get_irq_resource(struct acpi_resource *ares,
struct acpi_resource_gpio **agpio) struct acpi_resource_gpio **agpio)
...@@ -1222,16 +1223,28 @@ static inline bool acpi_gpio_get_io_resource(struct acpi_resource *ares, ...@@ -1222,16 +1223,28 @@ static inline bool acpi_gpio_get_io_resource(struct acpi_resource *ares,
{ {
return false; return false;
} }
static inline int acpi_dev_gpio_irq_get_by(struct acpi_device *adev, static inline int acpi_dev_gpio_irq_wake_get_by(struct acpi_device *adev, const char *name,
const char *name, int index) int index, bool *wake_capable)
{ {
return -ENXIO; return -ENXIO;
} }
#endif #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) 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 */ /* Device properties */
......
...@@ -79,7 +79,8 @@ struct resource { ...@@ -79,7 +79,8 @@ struct resource {
#define IORESOURCE_IRQ_HIGHLEVEL (1<<2) #define IORESOURCE_IRQ_HIGHLEVEL (1<<2)
#define IORESOURCE_IRQ_LOWLEVEL (1<<3) #define IORESOURCE_IRQ_LOWLEVEL (1<<3)
#define IORESOURCE_IRQ_SHAREABLE (1<<4) #define IORESOURCE_IRQ_SHAREABLE (1<<4)
#define IORESOURCE_IRQ_OPTIONAL (1<<5) #define IORESOURCE_IRQ_OPTIONAL (1<<5)
#define IORESOURCE_IRQ_WAKECAPABLE (1<<6)
/* PnP DMA specific bits (IORESOURCE_BITS) */ /* PnP DMA specific bits (IORESOURCE_BITS) */
#define IORESOURCE_DMA_TYPE_MASK (3<<0) #define IORESOURCE_DMA_TYPE_MASK (3<<0)
......
...@@ -105,6 +105,14 @@ enum sys_off_mode { ...@@ -105,6 +105,14 @@ enum sys_off_mode {
*/ */
SYS_OFF_MODE_POWER_OFF, 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: * @SYS_OFF_MODE_RESTART:
* *
......
...@@ -243,6 +243,17 @@ void migrate_to_reboot_cpu(void) ...@@ -243,6 +243,17 @@ void migrate_to_reboot_cpu(void)
set_cpus_allowed_ptr(current, cpumask_of(cpu)); 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 * kernel_restart - reboot the system
* @cmd: pointer to buffer containing command to execute for restart * @cmd: pointer to buffer containing command to execute for restart
...@@ -254,6 +265,7 @@ void migrate_to_reboot_cpu(void) ...@@ -254,6 +265,7 @@ void migrate_to_reboot_cpu(void)
void kernel_restart(char *cmd) void kernel_restart(char *cmd)
{ {
kernel_restart_prepare(cmd); kernel_restart_prepare(cmd);
do_kernel_restart_prepare();
migrate_to_reboot_cpu(); migrate_to_reboot_cpu();
syscore_shutdown(); syscore_shutdown();
if (!cmd) if (!cmd)
...@@ -396,6 +408,11 @@ register_sys_off_handler(enum sys_off_mode mode, ...@@ -396,6 +408,11 @@ register_sys_off_handler(enum sys_off_mode mode,
handler->list = &power_off_handler_list; handler->list = &power_off_handler_list;
break; break;
case SYS_OFF_MODE_RESTART_PREPARE:
handler->list = &restart_prep_handler_list;
handler->blocking = true;
break;
case SYS_OFF_MODE_RESTART: case SYS_OFF_MODE_RESTART:
handler->list = &restart_handler_list; handler->list = &restart_handler_list;
break; break;
......
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