From cb39dcdd4ef6a31028ecd663768b99e6230d3ee6 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 5 Nov 2014 18:34:45 +0200 Subject: ACPI / LPSS: add all LPSS devices to the specific power domain Currently the LPSS devices are located in the different power domains depends on LPSS_SAVE_CTX flag. We would like to use the specific power domain for all LPSS devices. The LPSS DMA controller has no knobs to control its power state. The specific power domain implementation will handle this case. The patch does a preparation for that. Signed-off-by: Andy Shevchenko Tested-by: Scott Ashcroft Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index 93d1606..f6b71af 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c @@ -499,14 +499,15 @@ static void acpi_lpss_set_ltr(struct device *dev, s32 val) /** * acpi_lpss_save_ctx() - Save the private registers of LPSS device * @dev: LPSS device + * @pdata: pointer to the private data of the LPSS device * * Most LPSS devices have private registers which may loose their context when * the device is powered down. acpi_lpss_save_ctx() saves those registers into * prv_reg_ctx array. */ -static void acpi_lpss_save_ctx(struct device *dev) +static void acpi_lpss_save_ctx(struct device *dev, + struct lpss_private_data *pdata) { - struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); unsigned int i; for (i = 0; i < LPSS_PRV_REG_COUNT; i++) { @@ -521,12 +522,13 @@ static void acpi_lpss_save_ctx(struct device *dev) /** * acpi_lpss_restore_ctx() - Restore the private registers of LPSS device * @dev: LPSS device + * @pdata: pointer to the private data of the LPSS device * * Restores the registers that were previously stored with acpi_lpss_save_ctx(). */ -static void acpi_lpss_restore_ctx(struct device *dev) +static void acpi_lpss_restore_ctx(struct device *dev, + struct lpss_private_data *pdata) { - struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); unsigned int i; /* @@ -549,23 +551,31 @@ static void acpi_lpss_restore_ctx(struct device *dev) #ifdef CONFIG_PM_SLEEP static int acpi_lpss_suspend_late(struct device *dev) { - int ret = pm_generic_suspend_late(dev); + struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); + int ret; + ret = pm_generic_suspend_late(dev); if (ret) return ret; - acpi_lpss_save_ctx(dev); + if (pdata->dev_desc->flags & LPSS_SAVE_CTX) + acpi_lpss_save_ctx(dev, pdata); + return acpi_dev_suspend_late(dev); } static int acpi_lpss_resume_early(struct device *dev) { - int ret = acpi_dev_resume_early(dev); + struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); + int ret; + ret = acpi_dev_resume_early(dev); if (ret) return ret; - acpi_lpss_restore_ctx(dev); + if (pdata->dev_desc->flags & LPSS_SAVE_CTX) + acpi_lpss_restore_ctx(dev, pdata); + return pm_generic_resume_early(dev); } #endif /* CONFIG_PM_SLEEP */ @@ -573,23 +583,31 @@ static int acpi_lpss_resume_early(struct device *dev) #ifdef CONFIG_PM_RUNTIME static int acpi_lpss_runtime_suspend(struct device *dev) { - int ret = pm_generic_runtime_suspend(dev); + struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); + int ret; + ret = pm_generic_runtime_suspend(dev); if (ret) return ret; - acpi_lpss_save_ctx(dev); + if (pdata->dev_desc->flags & LPSS_SAVE_CTX) + acpi_lpss_save_ctx(dev, pdata); + return acpi_dev_runtime_suspend(dev); } static int acpi_lpss_runtime_resume(struct device *dev) { - int ret = acpi_dev_runtime_resume(dev); + struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); + int ret; + ret = acpi_dev_runtime_resume(dev); if (ret) return ret; - acpi_lpss_restore_ctx(dev); + if (pdata->dev_desc->flags & LPSS_SAVE_CTX) + acpi_lpss_restore_ctx(dev, pdata); + return pm_generic_runtime_resume(dev); } #endif /* CONFIG_PM_RUNTIME */ @@ -631,22 +649,21 @@ static int acpi_lpss_platform_notify(struct notifier_block *nb, return 0; pdata = acpi_driver_data(adev); - if (!pdata || !pdata->mmio_base) + if (!pdata) return 0; - if (pdata->mmio_size < pdata->dev_desc->prv_offset + LPSS_LTR_SIZE) { + if (pdata->mmio_base && + pdata->mmio_size < pdata->dev_desc->prv_offset + LPSS_LTR_SIZE) { dev_err(&pdev->dev, "MMIO size insufficient to access LTR\n"); return 0; } switch (action) { case BUS_NOTIFY_BOUND_DRIVER: - if (pdata->dev_desc->flags & LPSS_SAVE_CTX) - pdev->dev.pm_domain = &acpi_lpss_pm_domain; + pdev->dev.pm_domain = &acpi_lpss_pm_domain; break; case BUS_NOTIFY_UNBOUND_DRIVER: - if (pdata->dev_desc->flags & LPSS_SAVE_CTX) - pdev->dev.pm_domain = NULL; + pdev->dev.pm_domain = NULL; break; case BUS_NOTIFY_ADD_DEVICE: if (pdata->dev_desc->flags & LPSS_LTR) -- cgit v0.10.2 From 01ac170ba29a9903ee590e1ef2d8e6b27b49a16c Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 5 Nov 2014 18:34:46 +0200 Subject: ACPI / LPSS: allow to use specific PM domain during ->probe() The LPSS DMA controller would like to use the specific PM domain callbacks during early stage, namely in ->probe(). This patch moves the specific PM domain assignment early to be accessible during a whole life time of the device in the system. Suggested-by: Rafael J. Wysocki Signed-off-by: Andy Shevchenko Tested-by: Scott Ashcroft Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index f6b71af..4804ae3 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c @@ -659,19 +659,17 @@ static int acpi_lpss_platform_notify(struct notifier_block *nb, } switch (action) { - case BUS_NOTIFY_BOUND_DRIVER: - pdev->dev.pm_domain = &acpi_lpss_pm_domain; - break; - case BUS_NOTIFY_UNBOUND_DRIVER: - pdev->dev.pm_domain = NULL; - break; case BUS_NOTIFY_ADD_DEVICE: + pdev->dev.pm_domain = &acpi_lpss_pm_domain; if (pdata->dev_desc->flags & LPSS_LTR) return sysfs_create_group(&pdev->dev.kobj, &lpss_attr_group); + break; case BUS_NOTIFY_DEL_DEVICE: if (pdata->dev_desc->flags & LPSS_LTR) sysfs_remove_group(&pdev->dev.kobj, &lpss_attr_group); + pdev->dev.pm_domain = NULL; + break; default: break; } -- cgit v0.10.2 From 6c17ee44d5240a247daef3cdc51a0c62d2b77d75 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 5 Nov 2014 18:34:47 +0200 Subject: ACPI / LPSS: introduce a 'proxy' device to power on LPSS for DMA The LPSS DMA controller does not have _PS0 and _PS3 methods. Moreover it can be powered off automatically whenever the last LPSS device goes down. In case of no power any access to the DMA controller will hang the system. The behaviour is reproduced on some HP laptops based on Intel Bay Trail [1] as well as on Asus T100 transformer. This patch introduces a so called 'proxy' device that has the knobs to handle a power of the LPSS island. When the system needs to program the DMA controller it calls to the ACPI LPSS power domain callbacks that wake or suspend the 'proxy' device. [1] http://www.spinics.net/lists/dmaengine/msg01514.html Suggested-by: Rafael J. Wysocki Signed-off-by: Andy Shevchenko Tested-by: Scott Ashcroft Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index 4804ae3..d1dd0ad 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c @@ -1,7 +1,7 @@ /* * ACPI support for Intel Lynxpoint LPSS. * - * Copyright (C) 2013, Intel Corporation + * Copyright (C) 2013, 2014, Intel Corporation * Authors: Mika Westerberg * Rafael J. Wysocki * @@ -60,6 +60,8 @@ ACPI_MODULE_NAME("acpi_lpss"); #define LPSS_CLK_DIVIDER BIT(2) #define LPSS_LTR BIT(3) #define LPSS_SAVE_CTX BIT(4) +#define LPSS_DEV_PROXY BIT(5) +#define LPSS_PROXY_REQ BIT(6) struct lpss_private_data; @@ -70,8 +72,10 @@ struct lpss_device_desc { void (*setup)(struct lpss_private_data *pdata); }; +static struct device *proxy_device; + static struct lpss_device_desc lpss_dma_desc = { - .flags = LPSS_CLK, + .flags = LPSS_CLK | LPSS_PROXY_REQ, }; struct lpss_private_data { @@ -146,22 +150,24 @@ static struct lpss_device_desc byt_pwm_dev_desc = { }; static struct lpss_device_desc byt_uart_dev_desc = { - .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_SAVE_CTX, + .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_SAVE_CTX | + LPSS_DEV_PROXY, .prv_offset = 0x800, .setup = lpss_uart_setup, }; static struct lpss_device_desc byt_spi_dev_desc = { - .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_SAVE_CTX, + .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_SAVE_CTX | + LPSS_DEV_PROXY, .prv_offset = 0x400, }; static struct lpss_device_desc byt_sdio_dev_desc = { - .flags = LPSS_CLK, + .flags = LPSS_CLK | LPSS_DEV_PROXY, }; static struct lpss_device_desc byt_i2c_dev_desc = { - .flags = LPSS_CLK | LPSS_SAVE_CTX, + .flags = LPSS_CLK | LPSS_SAVE_CTX | LPSS_DEV_PROXY, .prv_offset = 0x800, .setup = byt_i2c_setup, }; @@ -368,6 +374,8 @@ static int acpi_lpss_create_device(struct acpi_device *adev, adev->driver_data = pdata; pdev = acpi_create_platform_device(adev); if (!IS_ERR_OR_NULL(pdev)) { + if (!proxy_device && dev_desc->flags & LPSS_DEV_PROXY) + proxy_device = &pdev->dev; return 1; } @@ -593,7 +601,14 @@ static int acpi_lpss_runtime_suspend(struct device *dev) if (pdata->dev_desc->flags & LPSS_SAVE_CTX) acpi_lpss_save_ctx(dev, pdata); - return acpi_dev_runtime_suspend(dev); + ret = acpi_dev_runtime_suspend(dev); + if (ret) + return ret; + + if (pdata->dev_desc->flags & LPSS_PROXY_REQ && proxy_device) + return pm_runtime_put_sync_suspend(proxy_device); + + return 0; } static int acpi_lpss_runtime_resume(struct device *dev) @@ -601,6 +616,12 @@ static int acpi_lpss_runtime_resume(struct device *dev) struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); int ret; + if (pdata->dev_desc->flags & LPSS_PROXY_REQ && proxy_device) { + ret = pm_runtime_get_sync(proxy_device); + if (ret) + return ret; + } + ret = acpi_dev_runtime_resume(dev); if (ret) return ret; -- cgit v0.10.2 From bb32baf76e56cdb348633f4d789a93e81b975c47 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 5 Nov 2014 18:34:48 +0200 Subject: dmaengine: dw: enable runtime PM On runtime PM aware platforms the DMA have to manage its own power state. This patch enables runtime PM support and applies necessary calls wherever it's needed. Signed-off-by: Andy Shevchenko Acked-by: Vinod Koul Tested-by: Scott Ashcroft Signed-off-by: Rafael J. Wysocki diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c index 2447221..3804785 100644 --- a/drivers/dma/dw/core.c +++ b/drivers/dma/dw/core.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "../dmaengine.h" #include "internal.h" @@ -1504,6 +1505,9 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata) dw->regs = chip->regs; chip->dw = dw; + pm_runtime_enable(chip->dev); + pm_runtime_get_sync(chip->dev); + dw_params = dma_read_byaddr(chip->regs, DW_PARAMS); autocfg = dw_params >> DW_PARAMS_EN & 0x1; @@ -1667,11 +1671,14 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata) dev_info(chip->dev, "DesignWare DMA Controller, %d channels\n", nr_channels); + pm_runtime_put_sync_suspend(chip->dev); + return 0; err_dma_register: free_irq(chip->irq, dw); err_pdata: + pm_runtime_put_sync_suspend(chip->dev); return err; } EXPORT_SYMBOL_GPL(dw_dma_probe); @@ -1681,6 +1688,8 @@ int dw_dma_remove(struct dw_dma_chip *chip) struct dw_dma *dw = chip->dw; struct dw_dma_chan *dwc, *_dwc; + pm_runtime_get_sync(chip->dev); + dw_dma_off(dw); dma_async_device_unregister(&dw->dma); @@ -1693,6 +1702,8 @@ int dw_dma_remove(struct dw_dma_chip *chip) channel_clear_bit(dw, CH_EN, dwc->mask); } + pm_runtime_put_sync_suspend(chip->dev); + pm_runtime_disable(chip->dev); return 0; } EXPORT_SYMBOL_GPL(dw_dma_remove); -- cgit v0.10.2 From 24119a8829cdaf299294095ec568bf49e863c5a5 Mon Sep 17 00:00:00 2001 From: Hanjun Guo Date: Thu, 30 Oct 2014 17:52:58 +0800 Subject: ACPI / processor: Update the comments in processor.h In commit 46ba51e (ACPI / processor: Introduce ARCH_MIGHT_HAVE_ACPI_PDC), acpi_processor_set_pdc() was moved to processor_pdc.c, so update the comments accordingly. Signed-off-by: Hanjun Guo Signed-off-by: Rafael J. Wysocki diff --git a/include/acpi/processor.h b/include/acpi/processor.h index 9b9b6f2..cbb6cd3 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h @@ -313,11 +313,13 @@ static inline int acpi_processor_get_bios_limit(int cpu, unsigned int *limit) #endif /* CONFIG_CPU_FREQ */ /* in processor_core.c */ -void acpi_processor_set_pdc(acpi_handle handle); int acpi_get_apicid(acpi_handle, int type, u32 acpi_id); int acpi_map_cpuid(int apic_id, u32 acpi_id); int acpi_get_cpuid(acpi_handle, int type, u32 acpi_id); +/* in processor_pdc.c */ +void acpi_processor_set_pdc(acpi_handle handle); + /* in processor_throttling.c */ int acpi_processor_tstate_has_changed(struct acpi_processor *pr); int acpi_processor_get_throttling_info(struct acpi_processor *pr); -- cgit v0.10.2 From 40e7fcb19293cbdff02c74cb0668413480f82ea1 Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Sun, 23 Nov 2014 21:22:54 +0800 Subject: ACPI: Add _DEP support to fix battery issue on Asus T100TA ACPI 5.0 introduces _DEP (Operation Region Dependencies) to designate device objects that OSPM should assign a higher priority in start ordering due to future operation region accesses. On Asus T100TA, ACPI battery info are read from a I2C slave device via I2C operation region. Before I2C operation region handler is installed, battery _STA always returns 0. There is a _DEP method of designating start order under battery device node. This patch is to implement _DEP feature to fix battery issue on the Asus T100TA. Introducing acpi_dep_list and adding dep_unmet count in struct acpi_device. During ACPI namespace scan, create struct acpi_dep_data for a valid pair of master (device pointed to by _DEP)/ slave(device with _DEP), record master's and slave's ACPI handle in it and put it into acpi_dep_list. The dep_unmet count will increase by one if there is a device under its _DEP. Driver's probe() should return EPROBE_DEFER when find dep_unmet is larger than 0. When I2C operation region handler is installed, remove all struct acpi_dep_data on the acpi_dep_list whose master is pointed to I2C host controller and decrease slave's dep_unmet. When dep_unmet decreases to 0, all _DEP conditions are met and then do acpi_bus_attach() for the device in order to resolve battery _STA issue on the Asus T100TA. Link: https://bugzilla.kernel.org/show_bug.cgi?id=69011 Tested-by: Jan-Michael Brummer Tested-by: Adam Williamson Tested-by: Michael Shigorin Acked-by: Wolfram Sang Acked-by: Mika Westerberg Signed-off-by: Lan Tianyu Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 8ec8a89..d98ba43 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -1180,6 +1180,10 @@ static int acpi_battery_add(struct acpi_device *device) if (!device) return -EINVAL; + + if (device->dep_unmet) + return -EPROBE_DEFER; + battery = kzalloc(sizeof(struct acpi_battery), GFP_KERNEL); if (!battery) return -ENOMEM; diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 0476e90..00189ad 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -36,6 +36,8 @@ bool acpi_force_hot_remove; static const char *dummy_hid = "device"; +static LIST_HEAD(acpi_dep_list); +static DEFINE_MUTEX(acpi_dep_list_lock); static LIST_HEAD(acpi_bus_id_list); static DEFINE_MUTEX(acpi_scan_lock); static LIST_HEAD(acpi_scan_handlers_list); @@ -43,6 +45,12 @@ DEFINE_MUTEX(acpi_device_lock); LIST_HEAD(acpi_wakeup_device_list); static DEFINE_MUTEX(acpi_hp_context_lock); +struct acpi_dep_data { + struct list_head node; + acpi_handle master; + acpi_handle slave; +}; + struct acpi_device_bus_id{ char bus_id[15]; unsigned int instance_no; @@ -2086,6 +2094,59 @@ static void acpi_scan_init_hotplug(struct acpi_device *adev) } } +static void acpi_device_dep_initialize(struct acpi_device *adev) +{ + struct acpi_dep_data *dep; + struct acpi_handle_list dep_devices; + acpi_status status; + int i; + + if (!acpi_has_method(adev->handle, "_DEP")) + return; + + status = acpi_evaluate_reference(adev->handle, "_DEP", NULL, + &dep_devices); + if (ACPI_FAILURE(status)) { + dev_err(&adev->dev, "Failed to evaluate _DEP.\n"); + return; + } + + for (i = 0; i < dep_devices.count; i++) { + struct acpi_device_info *info; + int skip; + + status = acpi_get_object_info(dep_devices.handles[i], &info); + if (ACPI_FAILURE(status)) { + dev_err(&adev->dev, "Error reading device info\n"); + continue; + } + + /* + * Skip the dependency of Windows System Power + * Management Controller + */ + skip = info->valid & ACPI_VALID_HID && + !strcmp(info->hardware_id.string, "INT3396"); + + kfree(info); + + if (skip) + continue; + + dep = kzalloc(sizeof(struct acpi_dep_data), GFP_KERNEL); + if (!dep) + return; + + dep->master = dep_devices.handles[i]; + dep->slave = adev->handle; + adev->dep_unmet++; + + mutex_lock(&acpi_dep_list_lock); + list_add_tail(&dep->node , &acpi_dep_list); + mutex_unlock(&acpi_dep_list_lock); + } +} + static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used, void *not_used, void **return_value) { @@ -2112,6 +2173,7 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used, return AE_CTRL_DEPTH; acpi_scan_init_hotplug(device); + acpi_device_dep_initialize(device); out: if (!*return_value) @@ -2232,6 +2294,29 @@ static void acpi_bus_attach(struct acpi_device *device) device->handler->hotplug.notify_online(device); } +void acpi_walk_dep_device_list(acpi_handle handle) +{ + struct acpi_dep_data *dep, *tmp; + struct acpi_device *adev; + + mutex_lock(&acpi_dep_list_lock); + list_for_each_entry_safe(dep, tmp, &acpi_dep_list, node) { + if (dep->master == handle) { + acpi_bus_get_device(dep->slave, &adev); + if (!adev) + continue; + + adev->dep_unmet--; + if (!adev->dep_unmet) + acpi_bus_attach(adev); + list_del(&dep->node); + kfree(dep); + } + } + mutex_unlock(&acpi_dep_list_lock); +} +EXPORT_SYMBOL_GPL(acpi_walk_dep_device_list); + /** * acpi_bus_scan - Add ACPI device node objects in a given namespace scope. * @handle: Root of the namespace scope to scan. diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index f43b4e1..68aeb8e 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -403,6 +403,7 @@ static int acpi_i2c_install_space_handler(struct i2c_adapter *adapter) return -ENOMEM; } + acpi_walk_dep_device_list(handle); return 0; } diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index f34a083..ea3697d 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -359,6 +359,7 @@ struct acpi_device { void *driver_data; struct device dev; unsigned int physical_node_count; + unsigned int dep_unmet; struct list_head physical_node_list; struct mutex physical_node_lock; void (*remove)(struct acpi_device *); diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 407a12f..6cb3103 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -431,6 +431,7 @@ static inline bool acpi_driver_match_device(struct device *dev, int acpi_device_uevent_modalias(struct device *, struct kobj_uevent_env *); int acpi_device_modalias(struct device *, char *, int); +void acpi_walk_dep_device_list(acpi_handle handle); struct platform_device *acpi_create_platform_device(struct acpi_device *); #define ACPI_PTR(_ptr) (_ptr) -- cgit v0.10.2 From 75f9c2939a157c77d8342c53d3d4f016d3b067a3 Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Mon, 24 Nov 2014 19:56:38 +0800 Subject: ACPI / PM: Fixed a typo in a comment Signed-off-by: Huang Rui Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index 7db1931..076af81 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c @@ -201,7 +201,7 @@ int acpi_device_set_power(struct acpi_device *device, int state) * Transition Power * ---------------- * In accordance with the ACPI specification first apply power (via - * power resources) and then evalute _PSx. + * power resources) and then evaluate _PSx. */ if (device->power.flags.power_resources) { result = acpi_power_transition(device, state); -- cgit v0.10.2 From bccac16eeaa8c2428981891d09380672b229f48b Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Tue, 25 Nov 2014 14:48:49 +0000 Subject: ACPI / processor: remove unused variabled from acpi_processor_power structure Few elements in the acpi_processor_power structure are unused. It could be remnant in the header missed while the code got removed from the corresponding driver file. This patch removes those unused variables in the structure declaration. Signed-off-by: Sudeep Holla Signed-off-by: Rafael J. Wysocki diff --git a/include/acpi/processor.h b/include/acpi/processor.h index cbb6cd3..3ca9b75 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h @@ -67,9 +67,6 @@ struct acpi_processor_cx { }; struct acpi_processor_power { - struct acpi_processor_cx *state; - unsigned long bm_check_timestamp; - u32 default_state; int count; struct acpi_processor_cx states[ACPI_PROCESSOR_MAX_POWER]; int timer_broadcast_on_state; -- cgit v0.10.2 From 6fd8050a35475259c444afc6856d57f4bbd74231 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Tue, 25 Nov 2014 14:48:50 +0000 Subject: ACPI / cpuidle: avoid assigning signed errno to acpi_status It's incorrect to assign a signed value to an unsigned acpi_status variable. This patch fixes it by using a signed integer to return error values. Signed-off-by: Sudeep Holla Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 17f9ec5..38472fd 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -334,10 +334,10 @@ static int acpi_processor_get_power_info_default(struct acpi_processor *pr) static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) { - acpi_status status = 0; + acpi_status status; u64 count; int current_count; - int i; + int i, ret = 0; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *cst; @@ -358,7 +358,7 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) /* There must be at least 2 elements */ if (!cst || (cst->type != ACPI_TYPE_PACKAGE) || cst->package.count < 2) { printk(KERN_ERR PREFIX "not enough elements in _CST\n"); - status = -EFAULT; + ret = -EFAULT; goto end; } @@ -367,7 +367,7 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) /* Validate number of power states. */ if (count < 1 || count != cst->package.count - 1) { printk(KERN_ERR PREFIX "count given by _CST is not valid\n"); - status = -EFAULT; + ret = -EFAULT; goto end; } @@ -489,12 +489,12 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) /* Validate number of power states discovered */ if (current_count < 2) - status = -EFAULT; + ret = -EFAULT; end: kfree(buffer.pointer); - return status; + return ret; } static void acpi_processor_power_verify_c3(struct acpi_processor *pr, @@ -1111,7 +1111,7 @@ static int acpi_processor_registered; int acpi_processor_power_init(struct acpi_processor *pr) { - acpi_status status = 0; + acpi_status status; int retval; struct cpuidle_device *dev; static int first_run; -- cgit v0.10.2 From c52fa70c79acbb1d4868fee244a638d6ee6f5aab Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 1 Dec 2014 23:51:13 +0100 Subject: ACPI / sleep: Drain outstanding events after disabling multiple GPEs After multiple GPEs have been disabled at the low level in one go, like when acpi_disable_all_gpes() is called, we should always drain all of the outstanding events from them, or interesting races become possible. For this reason, call acpi_os_wait_events_complete() after acpi_enable_all_wakeup_gpes() and acpi_disable_all_gpes() in acpi_freeze_prepare() and acpi_power_off_prepare(), respectively. Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 05a31b5..8aa9254 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -630,6 +630,7 @@ static int acpi_freeze_begin(void) static int acpi_freeze_prepare(void) { acpi_enable_all_wakeup_gpes(); + acpi_os_wait_events_complete(); enable_irq_wake(acpi_gbl_FADT.sci_interrupt); return 0; } @@ -825,6 +826,7 @@ static void acpi_power_off_prepare(void) /* Prepare to power off the system */ acpi_sleep_prepare(ACPI_STATE_S5); acpi_disable_all_gpes(); + acpi_os_wait_events_complete(); } static void acpi_power_off(void) -- cgit v0.10.2