aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/acpi_lpss.c168
-rw-r--r--drivers/acpi/acpi_pnp.c6
-rw-r--r--drivers/acpi/acpica/aclocal.h1
-rw-r--r--drivers/acpi/acpica/acobject.h1
-rw-r--r--drivers/acpi/acpica/dsfield.c2
-rw-r--r--drivers/acpi/acpica/evregion.c47
-rw-r--r--drivers/acpi/acpica/evxfgpe.c32
-rw-r--r--drivers/acpi/acpica/exfield.c67
-rw-r--r--drivers/acpi/acpica/exprep.c2
-rw-r--r--drivers/acpi/acpica/hwgpe.c8
-rw-r--r--drivers/acpi/acpica/utresrc.c4
-rw-r--r--drivers/acpi/battery.c2
-rw-r--r--drivers/acpi/blacklist.c36
-rw-r--r--drivers/acpi/bus.c10
-rw-r--r--drivers/acpi/container.c8
-rw-r--r--drivers/acpi/device_pm.c71
-rw-r--r--drivers/acpi/fan.c18
-rw-r--r--drivers/acpi/osl.c12
-rw-r--r--drivers/acpi/pci_root.c14
-rw-r--r--drivers/acpi/processor_core.c6
-rw-r--r--drivers/acpi/sbs.c80
-rw-r--r--drivers/acpi/scan.c5
-rw-r--r--drivers/acpi/sleep.c16
-rw-r--r--drivers/acpi/utils.c1
-rw-r--r--drivers/acpi/video.c299
-rw-r--r--drivers/acpi/video_detect.c8
26 files changed, 443 insertions, 481 deletions
diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c
index fddc1e86f9d0..93d160661f4c 100644
--- a/drivers/acpi/acpi_lpss.c
+++ b/drivers/acpi/acpi_lpss.c
@@ -54,55 +54,58 @@ ACPI_MODULE_NAME("acpi_lpss");
#define LPSS_PRV_REG_COUNT 9
-struct lpss_shared_clock {
- const char *name;
- unsigned long rate;
- struct clk *clk;
-};
+/* LPSS Flags */
+#define LPSS_CLK BIT(0)
+#define LPSS_CLK_GATE BIT(1)
+#define LPSS_CLK_DIVIDER BIT(2)
+#define LPSS_LTR BIT(3)
+#define LPSS_SAVE_CTX BIT(4)
struct lpss_private_data;
struct lpss_device_desc {
- bool clk_required;
- const char *clkdev_name;
- bool ltr_required;
+ unsigned int flags;
unsigned int prv_offset;
size_t prv_size_override;
- bool clk_divider;
- bool clk_gate;
- bool save_ctx;
- struct lpss_shared_clock *shared_clock;
void (*setup)(struct lpss_private_data *pdata);
};
static struct lpss_device_desc lpss_dma_desc = {
- .clk_required = true,
- .clkdev_name = "hclk",
+ .flags = LPSS_CLK,
};
struct lpss_private_data {
void __iomem *mmio_base;
resource_size_t mmio_size;
+ unsigned int fixed_clk_rate;
struct clk *clk;
const struct lpss_device_desc *dev_desc;
u32 prv_reg_ctx[LPSS_PRV_REG_COUNT];
};
+/* UART Component Parameter Register */
+#define LPSS_UART_CPR 0xF4
+#define LPSS_UART_CPR_AFCE BIT(4)
+
static void lpss_uart_setup(struct lpss_private_data *pdata)
{
unsigned int offset;
- u32 reg;
+ u32 val;
offset = pdata->dev_desc->prv_offset + LPSS_TX_INT;
- reg = readl(pdata->mmio_base + offset);
- writel(reg | LPSS_TX_INT_MASK, pdata->mmio_base + offset);
-
- offset = pdata->dev_desc->prv_offset + LPSS_GENERAL;
- reg = readl(pdata->mmio_base + offset);
- writel(reg | LPSS_GENERAL_UART_RTS_OVRD, pdata->mmio_base + offset);
+ val = readl(pdata->mmio_base + offset);
+ writel(val | LPSS_TX_INT_MASK, pdata->mmio_base + offset);
+
+ val = readl(pdata->mmio_base + LPSS_UART_CPR);
+ if (!(val & LPSS_UART_CPR_AFCE)) {
+ offset = pdata->dev_desc->prv_offset + LPSS_GENERAL;
+ val = readl(pdata->mmio_base + offset);
+ val |= LPSS_GENERAL_UART_RTS_OVRD;
+ writel(val, pdata->mmio_base + offset);
+ }
}
-static void lpss_i2c_setup(struct lpss_private_data *pdata)
+static void byt_i2c_setup(struct lpss_private_data *pdata)
{
unsigned int offset;
u32 val;
@@ -111,100 +114,56 @@ static void lpss_i2c_setup(struct lpss_private_data *pdata)
val = readl(pdata->mmio_base + offset);
val |= LPSS_RESETS_RESET_APB | LPSS_RESETS_RESET_FUNC;
writel(val, pdata->mmio_base + offset);
-}
-static struct lpss_device_desc wpt_dev_desc = {
- .clk_required = true,
- .prv_offset = 0x800,
- .ltr_required = true,
- .clk_divider = true,
- .clk_gate = true,
-};
+ if (readl(pdata->mmio_base + pdata->dev_desc->prv_offset))
+ pdata->fixed_clk_rate = 133000000;
+}
static struct lpss_device_desc lpt_dev_desc = {
- .clk_required = true,
+ .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_LTR,
.prv_offset = 0x800,
- .ltr_required = true,
- .clk_divider = true,
- .clk_gate = true,
};
static struct lpss_device_desc lpt_i2c_dev_desc = {
- .clk_required = true,
+ .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_LTR,
.prv_offset = 0x800,
- .ltr_required = true,
- .clk_gate = true,
};
static struct lpss_device_desc lpt_uart_dev_desc = {
- .clk_required = true,
+ .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_LTR,
.prv_offset = 0x800,
- .ltr_required = true,
- .clk_divider = true,
- .clk_gate = true,
.setup = lpss_uart_setup,
};
static struct lpss_device_desc lpt_sdio_dev_desc = {
+ .flags = LPSS_LTR,
.prv_offset = 0x1000,
.prv_size_override = 0x1018,
- .ltr_required = true,
-};
-
-static struct lpss_shared_clock pwm_clock = {
- .name = "pwm_clk",
- .rate = 25000000,
};
static struct lpss_device_desc byt_pwm_dev_desc = {
- .clk_required = true,
- .save_ctx = true,
- .shared_clock = &pwm_clock,
+ .flags = LPSS_SAVE_CTX,
};
static struct lpss_device_desc byt_uart_dev_desc = {
- .clk_required = true,
+ .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_SAVE_CTX,
.prv_offset = 0x800,
- .clk_divider = true,
- .clk_gate = true,
- .save_ctx = true,
.setup = lpss_uart_setup,
};
static struct lpss_device_desc byt_spi_dev_desc = {
- .clk_required = true,
+ .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_SAVE_CTX,
.prv_offset = 0x400,
- .clk_divider = true,
- .clk_gate = true,
- .save_ctx = true,
};
static struct lpss_device_desc byt_sdio_dev_desc = {
- .clk_required = true,
-};
-
-static struct lpss_shared_clock i2c_clock = {
- .name = "i2c_clk",
- .rate = 100000000,
+ .flags = LPSS_CLK,
};
static struct lpss_device_desc byt_i2c_dev_desc = {
- .clk_required = true,
+ .flags = LPSS_CLK | LPSS_SAVE_CTX,
.prv_offset = 0x800,
- .save_ctx = true,
- .shared_clock = &i2c_clock,
- .setup = lpss_i2c_setup,
-};
-
-static struct lpss_shared_clock bsw_pwm_clock = {
- .name = "pwm_clk",
- .rate = 19200000,
-};
-
-static struct lpss_device_desc bsw_pwm_dev_desc = {
- .clk_required = true,
- .save_ctx = true,
- .shared_clock = &bsw_pwm_clock,
+ .setup = byt_i2c_setup,
};
#else
@@ -237,7 +196,7 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = {
{ "INT33FC", },
/* Braswell LPSS devices */
- { "80862288", LPSS_ADDR(bsw_pwm_dev_desc) },
+ { "80862288", LPSS_ADDR(byt_pwm_dev_desc) },
{ "8086228A", LPSS_ADDR(byt_uart_dev_desc) },
{ "8086228E", LPSS_ADDR(byt_spi_dev_desc) },
{ "808622C1", LPSS_ADDR(byt_i2c_dev_desc) },
@@ -251,7 +210,8 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = {
{ "INT3436", LPSS_ADDR(lpt_sdio_dev_desc) },
{ "INT3437", },
- { "INT3438", LPSS_ADDR(wpt_dev_desc) },
+ /* Wildcat Point LPSS devices */
+ { "INT3438", LPSS_ADDR(lpt_dev_desc) },
{ }
};
@@ -276,7 +236,6 @@ static int register_device_clock(struct acpi_device *adev,
struct lpss_private_data *pdata)
{
const struct lpss_device_desc *dev_desc = pdata->dev_desc;
- struct lpss_shared_clock *shared_clock = dev_desc->shared_clock;
const char *devname = dev_name(&adev->dev);
struct clk *clk = ERR_PTR(-ENODEV);
struct lpss_clk_data *clk_data;
@@ -289,12 +248,7 @@ static int register_device_clock(struct acpi_device *adev,
clk_data = platform_get_drvdata(lpss_clk_dev);
if (!clk_data)
return -ENODEV;
-
- if (dev_desc->clkdev_name) {
- clk_register_clkdev(clk_data->clk, dev_desc->clkdev_name,
- devname);
- return 0;
- }
+ clk = clk_data->clk;
if (!pdata->mmio_base
|| pdata->mmio_size < dev_desc->prv_offset + LPSS_CLK_SIZE)
@@ -303,24 +257,19 @@ static int register_device_clock(struct acpi_device *adev,
parent = clk_data->name;
prv_base = pdata->mmio_base + dev_desc->prv_offset;
- if (shared_clock) {
- clk = shared_clock->clk;
- if (!clk) {
- clk = clk_register_fixed_rate(NULL, shared_clock->name,
- "lpss_clk", 0,
- shared_clock->rate);
- shared_clock->clk = clk;
- }
- parent = shared_clock->name;
+ if (pdata->fixed_clk_rate) {
+ clk = clk_register_fixed_rate(NULL, devname, parent, 0,
+ pdata->fixed_clk_rate);
+ goto out;
}
- if (dev_desc->clk_gate) {
+ if (dev_desc->flags & LPSS_CLK_GATE) {
clk = clk_register_gate(NULL, devname, parent, 0,
prv_base, 0, 0, NULL);
parent = devname;
}
- if (dev_desc->clk_divider) {
+ if (dev_desc->flags & LPSS_CLK_DIVIDER) {
/* Prevent division by zero */
if (!readl(prv_base))
writel(LPSS_CLK_DIVIDER_DEF_MASK, prv_base);
@@ -344,7 +293,7 @@ static int register_device_clock(struct acpi_device *adev,
kfree(parent);
kfree(clk_name);
}
-
+out:
if (IS_ERR(clk))
return PTR_ERR(clk);
@@ -392,7 +341,10 @@ static int acpi_lpss_create_device(struct acpi_device *adev,
pdata->dev_desc = dev_desc;
- if (dev_desc->clk_required) {
+ if (dev_desc->setup)
+ dev_desc->setup(pdata);
+
+ if (dev_desc->flags & LPSS_CLK) {
ret = register_device_clock(adev, pdata);
if (ret) {
/* Skip the device, but continue the namespace scan. */
@@ -413,13 +365,9 @@ static int acpi_lpss_create_device(struct acpi_device *adev,
goto err_out;
}
- if (dev_desc->setup)
- dev_desc->setup(pdata);
-
adev->driver_data = pdata;
pdev = acpi_create_platform_device(adev);
if (!IS_ERR_OR_NULL(pdev)) {
- device_enable_async_suspend(&pdev->dev);
return 1;
}
@@ -693,19 +641,19 @@ static int acpi_lpss_platform_notify(struct notifier_block *nb,
switch (action) {
case BUS_NOTIFY_BOUND_DRIVER:
- if (pdata->dev_desc->save_ctx)
+ if (pdata->dev_desc->flags & LPSS_SAVE_CTX)
pdev->dev.pm_domain = &acpi_lpss_pm_domain;
break;
case BUS_NOTIFY_UNBOUND_DRIVER:
- if (pdata->dev_desc->save_ctx)
+ if (pdata->dev_desc->flags & LPSS_SAVE_CTX)
pdev->dev.pm_domain = NULL;
break;
case BUS_NOTIFY_ADD_DEVICE:
- if (pdata->dev_desc->ltr_required)
+ if (pdata->dev_desc->flags & LPSS_LTR)
return sysfs_create_group(&pdev->dev.kobj,
&lpss_attr_group);
case BUS_NOTIFY_DEL_DEVICE:
- if (pdata->dev_desc->ltr_required)
+ if (pdata->dev_desc->flags & LPSS_LTR)
sysfs_remove_group(&pdev->dev.kobj, &lpss_attr_group);
default:
break;
@@ -722,7 +670,7 @@ static void acpi_lpss_bind(struct device *dev)
{
struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev));
- if (!pdata || !pdata->mmio_base || !pdata->dev_desc->ltr_required)
+ if (!pdata || !pdata->mmio_base || !(pdata->dev_desc->flags & LPSS_LTR))
return;
if (pdata->mmio_size >= pdata->dev_desc->prv_offset + LPSS_LTR_SIZE)
diff --git a/drivers/acpi/acpi_pnp.c b/drivers/acpi/acpi_pnp.c
index 996fa1959eea..b193f8425999 100644
--- a/drivers/acpi/acpi_pnp.c
+++ b/drivers/acpi/acpi_pnp.c
@@ -15,8 +15,6 @@
#include <linux/ctype.h>
static const struct acpi_device_id acpi_pnp_device_ids[] = {
- /* soc_button_array */
- {"PNP0C40"},
/* pata_isapnp */
{"PNP0600"}, /* Generic ESDI/IDE/ATA compatible hard disk controller */
/* floppy */
@@ -132,10 +130,6 @@ static const struct acpi_device_id acpi_pnp_device_ids[] = {
{"PNP0401"}, /* ECP Printer Port */
/* apple-gmux */
{"APP000B"},
- /* fujitsu-laptop.c */
- {"FUJ02bf"},
- {"FUJ02B1"},
- {"FUJ02E3"},
/* system */
{"PNP0c02"}, /* General ID for reserving resources */
{"PNP0c01"}, /* memory controller */
diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h
index 1f9aba5fb81f..2747279fbe3c 100644
--- a/drivers/acpi/acpica/aclocal.h
+++ b/drivers/acpi/acpica/aclocal.h
@@ -254,6 +254,7 @@ struct acpi_create_field_info {
u32 field_bit_position;
u32 field_bit_length;
u16 resource_length;
+ u16 pin_number_index;
u8 field_flags;
u8 attribute;
u8 field_type;
diff --git a/drivers/acpi/acpica/acobject.h b/drivers/acpi/acpica/acobject.h
index 22fb6449d3d6..8abb393dafab 100644
--- a/drivers/acpi/acpica/acobject.h
+++ b/drivers/acpi/acpica/acobject.h
@@ -264,6 +264,7 @@ struct acpi_object_region_field {
ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO u16 resource_length;
union acpi_operand_object *region_obj; /* Containing op_region object */
u8 *resource_buffer; /* resource_template for serial regions/fields */
+ u16 pin_number_index; /* Index relative to previous Connection/Template */
};
struct acpi_object_bank_field {
diff --git a/drivers/acpi/acpica/dsfield.c b/drivers/acpi/acpica/dsfield.c
index 3661c8e90540..c57666196672 100644
--- a/drivers/acpi/acpica/dsfield.c
+++ b/drivers/acpi/acpica/dsfield.c
@@ -360,6 +360,7 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info,
*/
info->resource_buffer = NULL;
info->connection_node = NULL;
+ info->pin_number_index = 0;
/*
* A Connection() is either an actual resource descriptor (buffer)
@@ -437,6 +438,7 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info,
}
info->field_bit_position += info->field_bit_length;
+ info->pin_number_index++; /* Index relative to previous Connection() */
break;
default:
diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c
index 9957297d1580..8eb8575e8c16 100644
--- a/drivers/acpi/acpica/evregion.c
+++ b/drivers/acpi/acpica/evregion.c
@@ -142,6 +142,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
union acpi_operand_object *region_obj2;
void *region_context = NULL;
struct acpi_connection_info *context;
+ acpi_physical_address address;
ACPI_FUNCTION_TRACE(ev_address_space_dispatch);
@@ -231,25 +232,23 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
/* We have everything we need, we can invoke the address space handler */
handler = handler_desc->address_space.handler;
-
- ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
- "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
- &region_obj->region.handler->address_space, handler,
- ACPI_FORMAT_NATIVE_UINT(region_obj->region.address +
- region_offset),
- acpi_ut_get_region_name(region_obj->region.
- space_id)));
+ address = (region_obj->region.address + region_offset);
/*
* Special handling for generic_serial_bus and general_purpose_io:
* There are three extra parameters that must be passed to the
* handler via the context:
- * 1) Connection buffer, a resource template from Connection() op.
- * 2) Length of the above buffer.
- * 3) Actual access length from the access_as() op.
+ * 1) Connection buffer, a resource template from Connection() op
+ * 2) Length of the above buffer
+ * 3) Actual access length from the access_as() op
+ *
+ * In addition, for general_purpose_io, the Address and bit_width fields
+ * are defined as follows:
+ * 1) Address is the pin number index of the field (bit offset from
+ * the previous Connection)
+ * 2) bit_width is the actual bit length of the field (number of pins)
*/
- if (((region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS) ||
- (region_obj->region.space_id == ACPI_ADR_SPACE_GPIO)) &&
+ if ((region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS) &&
context && field_obj) {
/* Get the Connection (resource_template) buffer */
@@ -258,6 +257,24 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
context->length = field_obj->field.resource_length;
context->access_length = field_obj->field.access_length;
}
+ if ((region_obj->region.space_id == ACPI_ADR_SPACE_GPIO) &&
+ context && field_obj) {
+
+ /* Get the Connection (resource_template) buffer */
+
+ context->connection = field_obj->field.resource_buffer;
+ context->length = field_obj->field.resource_length;
+ context->access_length = field_obj->field.access_length;
+ address = field_obj->field.pin_number_index;
+ bit_width = field_obj->field.bit_length;
+ }
+
+ ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
+ "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
+ &region_obj->region.handler->address_space, handler,
+ ACPI_FORMAT_NATIVE_UINT(address),
+ acpi_ut_get_region_name(region_obj->region.
+ space_id)));
if (!(handler_desc->address_space.handler_flags &
ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
@@ -271,9 +288,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
/* Call the handler */
- status = handler(function,
- (region_obj->region.address + region_offset),
- bit_width, value, context,
+ status = handler(function, address, bit_width, value, context,
region_obj2->extra.region_context);
if (ACPI_FAILURE(status)) {
diff --git a/drivers/acpi/acpica/evxfgpe.c b/drivers/acpi/acpica/evxfgpe.c
index 0cf159cc6e6d..56710a03c9b0 100644
--- a/drivers/acpi/acpica/evxfgpe.c
+++ b/drivers/acpi/acpica/evxfgpe.c
@@ -596,6 +596,38 @@ acpi_status acpi_enable_all_runtime_gpes(void)
ACPI_EXPORT_SYMBOL(acpi_enable_all_runtime_gpes)
+/******************************************************************************
+ *
+ * FUNCTION: acpi_enable_all_wakeup_gpes
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Enable all "wakeup" GPEs and disable all of the other GPEs, in
+ * all GPE blocks.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_enable_all_wakeup_gpes(void)
+{
+ acpi_status status;
+
+ ACPI_FUNCTION_TRACE(acpi_enable_all_wakeup_gpes);
+
+ status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+
+ status = acpi_hw_enable_all_wakeup_gpes();
+ (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
+
+ return_ACPI_STATUS(status);
+}
+
+ACPI_EXPORT_SYMBOL(acpi_enable_all_wakeup_gpes)
+
/*******************************************************************************
*
* FUNCTION: acpi_install_gpe_block
diff --git a/drivers/acpi/acpica/exfield.c b/drivers/acpi/acpica/exfield.c
index 6907ce0c704c..b994845ed359 100644
--- a/drivers/acpi/acpica/exfield.c
+++ b/drivers/acpi/acpica/exfield.c
@@ -253,6 +253,37 @@ acpi_ex_read_data_from_field(struct acpi_walk_state * walk_state,
buffer = &buffer_desc->integer.value;
}
+ if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
+ (obj_desc->field.region_obj->region.space_id ==
+ ACPI_ADR_SPACE_GPIO)) {
+ /*
+ * For GPIO (general_purpose_io), the Address will be the bit offset
+ * from the previous Connection() operator, making it effectively a
+ * pin number index. The bit_length is the length of the field, which
+ * is thus the number of pins.
+ */
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+ "GPIO FieldRead [FROM]: Pin %u Bits %u\n",
+ obj_desc->field.pin_number_index,
+ obj_desc->field.bit_length));
+
+ /* Lock entire transaction if requested */
+
+ acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
+
+ /* Perform the write */
+
+ status = acpi_ex_access_region(obj_desc, 0,
+ (u64 *)buffer, ACPI_READ);
+ acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
+ if (ACPI_FAILURE(status)) {
+ acpi_ut_remove_reference(buffer_desc);
+ } else {
+ *ret_buffer_desc = buffer_desc;
+ }
+ return_ACPI_STATUS(status);
+ }
+
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
"FieldRead [TO]: Obj %p, Type %X, Buf %p, ByteLen %X\n",
obj_desc, obj_desc->common.type, buffer,
@@ -413,6 +444,42 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
*result_desc = buffer_desc;
return_ACPI_STATUS(status);
+ } else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
+ (obj_desc->field.region_obj->region.space_id ==
+ ACPI_ADR_SPACE_GPIO)) {
+ /*
+ * For GPIO (general_purpose_io), we will bypass the entire field
+ * mechanism and handoff the bit address and bit width directly to
+ * the handler. The Address will be the bit offset
+ * from the previous Connection() operator, making it effectively a
+ * pin number index. The bit_length is the length of the field, which
+ * is thus the number of pins.
+ */
+ if (source_desc->common.type != ACPI_TYPE_INTEGER) {
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
+ }
+
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+ "GPIO FieldWrite [FROM]: (%s:%X), Val %.8X [TO]: Pin %u Bits %u\n",
+ acpi_ut_get_type_name(source_desc->common.
+ type),
+ source_desc->common.type,
+ (u32)source_desc->integer.value,
+ obj_desc->field.pin_number_index,
+ obj_desc->field.bit_length));
+
+ buffer = &source_desc->integer.value;
+
+ /* Lock entire transaction if requested */
+
+ acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
+
+ /* Perform the write */
+
+ status = acpi_ex_access_region(obj_desc, 0,
+ (u64 *)buffer, ACPI_WRITE);
+ acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
+ return_ACPI_STATUS(status);
}
/* Get a pointer to the data to be written */
diff --git a/drivers/acpi/acpica/exprep.c b/drivers/acpi/acpica/exprep.c
index ee3f872870bc..118e942005e5 100644
--- a/drivers/acpi/acpica/exprep.c
+++ b/drivers/acpi/acpica/exprep.c
@@ -484,6 +484,8 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
obj_desc->field.resource_length = info->resource_length;
}
+ obj_desc->field.pin_number_index = info->pin_number_index;
+
/* Allow full data read from EC address space */
if ((obj_desc->field.region_obj->region.space_id ==
diff --git a/drivers/acpi/acpica/hwgpe.c b/drivers/acpi/acpica/hwgpe.c
index 2e6caabba07a..ea62d40fd161 100644
--- a/drivers/acpi/acpica/hwgpe.c
+++ b/drivers/acpi/acpica/hwgpe.c
@@ -396,11 +396,11 @@ acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
/* Examine each GPE Register within the block */
for (i = 0; i < gpe_block->register_count; i++) {
- if (!gpe_block->register_info[i].enable_for_wake) {
- continue;
- }
- /* Enable all "wake" GPEs in this register */
+ /*
+ * Enable all "wake" GPEs in this register and disable the
+ * remaining ones.
+ */
status =
acpi_hw_write(gpe_block->register_info[i].enable_for_wake,
diff --git a/drivers/acpi/acpica/utresrc.c b/drivers/acpi/acpica/utresrc.c
index 14cb6c0c8be2..5cd017c7ac0e 100644
--- a/drivers/acpi/acpica/utresrc.c
+++ b/drivers/acpi/acpica/utresrc.c
@@ -87,7 +87,9 @@ const char *acpi_gbl_io_decode[] = {
const char *acpi_gbl_ll_decode[] = {
"ActiveHigh",
- "ActiveLow"
+ "ActiveLow",
+ "ActiveBoth",
+ "Reserved"
};
const char *acpi_gbl_max_decode[] = {
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 5fdfe65fe165..8ec8a89a20ab 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -695,7 +695,7 @@ static void acpi_battery_quirks(struct acpi_battery *battery)
if (battery->power_unit && dmi_name_in_vendors("LENOVO")) {
const char *s;
s = dmi_get_system_info(DMI_PRODUCT_VERSION);
- if (s && !strnicmp(s, "ThinkPad", 8)) {
+ if (s && !strncasecmp(s, "ThinkPad", 8)) {
dmi_walk(find_battery, battery);
if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH,
&battery->flags) &&
diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c
index 36eb42e3b0bb..ed122e17636e 100644
--- a/drivers/acpi/blacklist.c
+++ b/drivers/acpi/blacklist.c
@@ -247,8 +247,8 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
},
/*
- * These machines will power on immediately after shutdown when
- * reporting the Windows 2012 OSI.
+ * The wireless hotkey does not work on those machines when
+ * returning true for _OSI("Windows 2012")
*/
{
.callback = dmi_disable_osi_win8,
@@ -258,6 +258,38 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7737"),
},
},
+ {
+ .callback = dmi_disable_osi_win8,
+ .ident = "Dell Inspiron 7537",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7537"),
+ },
+ },
+ {
+ .callback = dmi_disable_osi_win8,
+ .ident = "Dell Inspiron 5437",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 5437"),
+ },
+ },
+ {
+ .callback = dmi_disable_osi_win8,
+ .ident = "Dell Inspiron 3437",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 3437"),
+ },
+ },
+ {
+ .callback = dmi_disable_osi_win8,
+ .ident = "Dell Vostro 3446",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3446"),
+ },
+ },
/*
* BIOS invocation of _OSI(Linux) is almost always a BIOS bug.
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 8581f5b84f48..8b67bd0f6bb5 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -177,16 +177,6 @@ void acpi_bus_detach_private_data(acpi_handle handle)
}
EXPORT_SYMBOL_GPL(acpi_bus_detach_private_data);
-void acpi_bus_no_hotplug(acpi_handle handle)
-{
- struct acpi_device *adev = NULL;
-
- acpi_bus_get_device(handle, &adev);
- if (adev)
- adev->flags.no_hotplug = true;
-}
-EXPORT_SYMBOL_GPL(acpi_bus_no_hotplug);
-
static void acpi_print_osc_error(acpi_handle handle,
struct acpi_osc_context *context, char *error)
{
diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c
index 76f7cff64594..c8ead9f97375 100644
--- a/drivers/acpi/container.c
+++ b/drivers/acpi/container.c
@@ -99,6 +99,13 @@ static void container_device_detach(struct acpi_device *adev)
device_unregister(dev);
}
+static void container_device_online(struct acpi_device *adev)
+{
+ struct device *dev = acpi_driver_data(adev);
+
+ kobject_uevent(&dev->kobj, KOBJ_ONLINE);
+}
+
static struct acpi_scan_handler container_handler = {
.ids = container_device_ids,
.attach = container_device_attach,
@@ -106,6 +113,7 @@ static struct acpi_scan_handler container_handler = {
.hotplug = {
.enabled = true,
.demand_offline = true,
+ .notify_online = container_device_online,
},
};
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c
index 67075f800e34..bea6896be122 100644
--- a/drivers/acpi/device_pm.c
+++ b/drivers/acpi/device_pm.c
@@ -1041,6 +1041,40 @@ static struct dev_pm_domain acpi_general_pm_domain = {
};
/**
+ * acpi_dev_pm_detach - Remove ACPI power management from the device.
+ * @dev: Device to take care of.
+ * @power_off: Whether or not to try to remove power from the device.
+ *
+ * Remove the device from the general ACPI PM domain and remove its wakeup
+ * notifier. If @power_off is set, additionally remove power from the device if
+ * possible.
+ *
+ * Callers must ensure proper synchronization of this function with power
+ * management callbacks.
+ */
+static void acpi_dev_pm_detach(struct device *dev, bool power_off)
+{
+ struct acpi_device *adev = ACPI_COMPANION(dev);
+
+ if (adev && dev->pm_domain == &acpi_general_pm_domain) {
+ dev->pm_domain = NULL;
+ acpi_remove_pm_notifier(adev);
+ if (power_off) {
+ /*
+ * If the device's PM QoS resume latency limit or flags
+ * have been exposed to user space, they have to be
+ * hidden at this point, so that they don't affect the
+ * choice of the low-power state to put the device into.
+ */
+ dev_pm_qos_hide_latency_limit(dev);
+ dev_pm_qos_hide_flags(dev);
+ acpi_device_wakeup(adev, ACPI_STATE_S0, false);
+ acpi_dev_pm_low_power(dev, adev, ACPI_STATE_S0);
+ }
+ }
+}
+
+/**
* acpi_dev_pm_attach - Prepare device for ACPI power management.
* @dev: Device to prepare.
* @power_on: Whether or not to power on the device.
@@ -1072,42 +1106,9 @@ int acpi_dev_pm_attach(struct device *dev, bool power_on)
acpi_dev_pm_full_power(adev);
acpi_device_wakeup(adev, ACPI_STATE_S0, false);
}
+
+ dev->pm_domain->detach = acpi_dev_pm_detach;
return 0;
}
EXPORT_SYMBOL_GPL(acpi_dev_pm_attach);
-
-/**
- * acpi_dev_pm_detach - Remove ACPI power management from the device.
- * @dev: Device to take care of.
- * @power_off: Whether or not to try to remove power from the device.
- *
- * Remove the device from the general ACPI PM domain and remove its wakeup
- * notifier. If @power_off is set, additionally remove power from the device if
- * possible.
- *
- * Callers must ensure proper synchronization of this function with power
- * management callbacks.
- */
-void acpi_dev_pm_detach(struct device *dev, bool power_off)
-{
- struct acpi_device *adev = ACPI_COMPANION(dev);
-
- if (adev && dev->pm_domain == &acpi_general_pm_domain) {
- dev->pm_domain = NULL;
- acpi_remove_pm_notifier(adev);
- if (power_off) {
- /*
- * If the device's PM QoS resume latency limit or flags
- * have been exposed to user space, they have to be
- * hidden at this point, so that they don't affect the
- * choice of the low-power state to put the device into.
- */
- dev_pm_qos_hide_latency_limit(dev);
- dev_pm_qos_hide_flags(dev);
- acpi_device_wakeup(adev, ACPI_STATE_S0, false);
- acpi_dev_pm_low_power(dev, adev, ACPI_STATE_S0);
- }
- }
-}
-EXPORT_SYMBOL_GPL(acpi_dev_pm_detach);
#endif /* CONFIG_PM */
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
index 8acf53e62966..5328b1090e08 100644
--- a/drivers/acpi/fan.c
+++ b/drivers/acpi/fan.c
@@ -27,12 +27,10 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <linux/thermal.h>
#include <linux/acpi.h>
-#define PREFIX "ACPI: "
-
#define ACPI_FAN_CLASS "fan"
#define ACPI_FAN_FILE_STATE "state"
@@ -127,8 +125,9 @@ static const struct thermal_cooling_device_ops fan_cooling_ops = {
};
/* --------------------------------------------------------------------------
- Driver Interface
- -------------------------------------------------------------------------- */
+ * Driver Interface
+ * --------------------------------------------------------------------------
+*/
static int acpi_fan_add(struct acpi_device *device)
{
@@ -143,7 +142,7 @@ static int acpi_fan_add(struct acpi_device *device)
result = acpi_bus_update_power(device->handle, NULL);
if (result) {
- printk(KERN_ERR PREFIX "Setting initial power state\n");
+ dev_err(&device->dev, "Setting initial power state\n");
goto end;
}
@@ -168,10 +167,9 @@ static int acpi_fan_add(struct acpi_device *device)
&device->dev.kobj,
"device");
if (result)
- dev_err(&device->dev, "Failed to create sysfs link "
- "'device'\n");
+ dev_err(&device->dev, "Failed to create sysfs link 'device'\n");
- printk(KERN_INFO PREFIX "%s [%s] (%s)\n",
+ dev_info(&device->dev, "ACPI: %s [%s] (%s)\n",
acpi_device_name(device), acpi_device_bid(device),
!device->power.state ? "on" : "off");
@@ -217,7 +215,7 @@ static int acpi_fan_resume(struct device *dev)
result = acpi_bus_update_power(to_acpi_device(dev)->handle, NULL);
if (result)
- printk(KERN_ERR PREFIX "Error updating fan power state\n");
+ dev_err(dev, "Error updating fan power state\n");
return result;
}
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 3abe9b223ba7..9964f70be98d 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -152,6 +152,16 @@ static u32 acpi_osi_handler(acpi_string interface, u32 supported)
osi_linux.dmi ? " via DMI" : "");
}
+ if (!strcmp("Darwin", interface)) {
+ /*
+ * Apple firmware will behave poorly if it receives positive
+ * answers to "Darwin" and any other OS. Respond positively
+ * to Darwin and then disable all other vendor strings.
+ */
+ acpi_update_interfaces(ACPI_DISABLE_ALL_VENDOR_STRINGS);
+ supported = ACPI_UINT32_MAX;
+ }
+
return supported;
}
@@ -825,7 +835,7 @@ acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler,
acpi_irq_handler = handler;
acpi_irq_context = context;
- if (request_irq(irq, acpi_irq, IRQF_SHARED | IRQF_NO_SUSPEND, "acpi", acpi_irq)) {
+ if (request_irq(irq, acpi_irq, IRQF_SHARED, "acpi", acpi_irq)) {
printk(KERN_ERR PREFIX "SCI (IRQ%d) allocation failed\n", irq);
acpi_irq_handler = NULL;
return AE_NOT_ACQUIRED;
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index e6ae603ed1a1..cd4de7e038ea 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -35,6 +35,7 @@
#include <linux/pci-aspm.h>
#include <linux/acpi.h>
#include <linux/slab.h>
+#include <linux/dmi.h>
#include <acpi/apei.h> /* for acpi_hest_init() */
#include "internal.h"
@@ -430,6 +431,19 @@ static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm,
acpi_handle handle = device->handle;
/*
+ * Apple always return failure on _OSC calls when _OSI("Darwin") has
+ * been called successfully. We know the feature set supported by the
+ * platform, so avoid calling _OSC at all
+ */
+
+ if (dmi_match(DMI_SYS_VENDOR, "Apple Inc.")) {
+ root->osc_control_set = ~OSC_PCI_EXPRESS_PME_CONTROL;
+ decode_osc_control(root, "OS assumes control of",
+ root->osc_control_set);
+ return;
+ }
+
+ /*
* All supported architectures that use ACPI have support for
* PCI domains, so we indicate this in _OSC support capabilities.
*/
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index e32321ce9a5c..ef58f46c8442 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -16,7 +16,7 @@ static int map_lapic_id(struct acpi_subtable_header *entry,
u32 acpi_id, int *apic_id)
{
struct acpi_madt_local_apic *lapic =
- (struct acpi_madt_local_apic *)entry;
+ container_of(entry, struct acpi_madt_local_apic, header);
if (!(lapic->lapic_flags & ACPI_MADT_ENABLED))
return -ENODEV;
@@ -32,7 +32,7 @@ static int map_x2apic_id(struct acpi_subtable_header *entry,
int device_declaration, u32 acpi_id, int *apic_id)
{
struct acpi_madt_local_x2apic *apic =
- (struct acpi_madt_local_x2apic *)entry;
+ container_of(entry, struct acpi_madt_local_x2apic, header);
if (!(apic->lapic_flags & ACPI_MADT_ENABLED))
return -ENODEV;
@@ -49,7 +49,7 @@ static int map_lsapic_id(struct acpi_subtable_header *entry,
int device_declaration, u32 acpi_id, int *apic_id)
{
struct acpi_madt_local_sapic *lsapic =
- (struct acpi_madt_local_sapic *)entry;
+ container_of(entry, struct acpi_madt_local_sapic, header);
if (!(lsapic->lapic_flags & ACPI_MADT_ENABLED))
return -ENODEV;
diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c
index 366ca40a6f70..a7a3edd28beb 100644
--- a/drivers/acpi/sbs.c
+++ b/drivers/acpi/sbs.c
@@ -35,6 +35,7 @@
#include <linux/jiffies.h>
#include <linux/delay.h>
#include <linux/power_supply.h>
+#include <linux/dmi.h>
#include "sbshc.h"
#include "battery.h"
@@ -61,6 +62,8 @@ static unsigned int cache_time = 1000;
module_param(cache_time, uint, 0644);
MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
+static bool sbs_manager_broken;
+
#define MAX_SBS_BAT 4
#define ACPI_SBS_BLOCK_MAX 32
@@ -109,6 +112,7 @@ struct acpi_sbs {
u8 batteries_supported:4;
u8 manager_present:1;
u8 charger_present:1;
+ u8 charger_exists:1;
};
#define to_acpi_sbs(x) container_of(x, struct acpi_sbs, charger)
@@ -429,9 +433,19 @@ static int acpi_ac_get_present(struct acpi_sbs *sbs)
result = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_CHARGER,
0x13, (u8 *) & status);
- if (!result)
- sbs->charger_present = (status >> 15) & 0x1;
- return result;
+
+ if (result)
+ return result;
+
+ /*
+ * The spec requires that bit 4 always be 1. If it's not set, assume
+ * that the implementation doesn't support an SBS charger
+ */
+ if (!((status >> 4) & 0x1))
+ return -ENODEV;
+
+ sbs->charger_present = (status >> 15) & 0x1;
+ return 0;
}
static ssize_t acpi_battery_alarm_show(struct device *dev,
@@ -483,16 +497,21 @@ static int acpi_battery_read(struct acpi_battery *battery)
ACPI_SBS_MANAGER, 0x01, (u8 *)&state, 2);
} else if (battery->id == 0)
battery->present = 1;
+
if (result || !battery->present)
return result;
if (saved_present != battery->present) {
battery->update_time = 0;
result = acpi_battery_get_info(battery);
- if (result)
+ if (result) {
+ battery->present = 0;
return result;
+ }
}
result = acpi_battery_get_state(battery);
+ if (result)
+ battery->present = 0;
return result;
}
@@ -524,6 +543,7 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id)
result = power_supply_register(&sbs->device->dev, &battery->bat);
if (result)
goto end;
+
result = device_create_file(battery->bat.dev, &alarm_attr);
if (result)
goto end;
@@ -554,6 +574,7 @@ static int acpi_charger_add(struct acpi_sbs *sbs)
if (result)
goto end;
+ sbs->charger_exists = 1;
sbs->charger.name = "sbs-charger";
sbs->charger.type = POWER_SUPPLY_TYPE_MAINS;
sbs->charger.properties = sbs_ac_props;
@@ -580,9 +601,12 @@ static void acpi_sbs_callback(void *context)
struct acpi_battery *bat;
u8 saved_charger_state = sbs->charger_present;
u8 saved_battery_state;
- acpi_ac_get_present(sbs);
- if (sbs->charger_present != saved_charger_state)
- kobject_uevent(&sbs->charger.dev->kobj, KOBJ_CHANGE);
+
+ if (sbs->charger_exists) {
+ acpi_ac_get_present(sbs);
+ if (sbs->charger_present != saved_charger_state)
+ kobject_uevent(&sbs->charger.dev->kobj, KOBJ_CHANGE);
+ }
if (sbs->manager_present) {
for (id = 0; id < MAX_SBS_BAT; ++id) {
@@ -598,12 +622,31 @@ static void acpi_sbs_callback(void *context)
}
}
+static int disable_sbs_manager(const struct dmi_system_id *d)
+{
+ sbs_manager_broken = true;
+ return 0;
+}
+
+static struct dmi_system_id acpi_sbs_dmi_table[] = {
+ {
+ .callback = disable_sbs_manager,
+ .ident = "Apple",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc.")
+ },
+ },
+ { },
+};
+
static int acpi_sbs_add(struct acpi_device *device)
{
struct acpi_sbs *sbs;
int result = 0;
int id;
+ dmi_check_system(acpi_sbs_dmi_table);
+
sbs = kzalloc(sizeof(struct acpi_sbs), GFP_KERNEL);
if (!sbs) {
result = -ENOMEM;
@@ -619,17 +662,24 @@ static int acpi_sbs_add(struct acpi_device *device)
device->driver_data = sbs;
result = acpi_charger_add(sbs);
- if (result)
+ if (result && result != -ENODEV)
goto end;
- result = acpi_manager_get_info(sbs);
- if (!result) {
- sbs->manager_present = 1;
- for (id = 0; id < MAX_SBS_BAT; ++id)
- if ((sbs->batteries_supported & (1 << id)))
- acpi_battery_add(sbs, id);
- } else
+ result = 0;
+
+ if (!sbs_manager_broken) {
+ result = acpi_manager_get_info(sbs);
+ if (!result) {
+ sbs->manager_present = 0;
+ for (id = 0; id < MAX_SBS_BAT; ++id)
+ if ((sbs->batteries_supported & (1 << id)))
+ acpi_battery_add(sbs, id);
+ }
+ }
+
+ if (!sbs->manager_present)
acpi_battery_add(sbs, 0);
+
acpi_smbus_register_callback(sbs->hc, acpi_sbs_callback, sbs);
end:
if (result)
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 3bf7764659a4..ae44d8654c82 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -130,7 +130,7 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias,
list_for_each_entry(id, &acpi_dev->pnp.ids, list) {
count = snprintf(&modalias[len], size, "%s:", id->id);
if (count < 0)
- return EINVAL;
+ return -EINVAL;
if (count >= size)
return -ENOMEM;
len += count;
@@ -2189,6 +2189,9 @@ static void acpi_bus_attach(struct acpi_device *device)
ok:
list_for_each_entry(child, &device->children, node)
acpi_bus_attach(child);
+
+ if (device->handler && device->handler->hotplug.notify_online)
+ device->handler->hotplug.notify_online(device);
}
/**
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index 54da4a3fe65e..05a31b573fc3 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -14,6 +14,7 @@
#include <linux/irq.h>
#include <linux/dmi.h>
#include <linux/device.h>
+#include <linux/interrupt.h>
#include <linux/suspend.h>
#include <linux/reboot.h>
#include <linux/acpi.h>
@@ -626,6 +627,19 @@ static int acpi_freeze_begin(void)
return 0;
}
+static int acpi_freeze_prepare(void)
+{
+ acpi_enable_all_wakeup_gpes();
+ enable_irq_wake(acpi_gbl_FADT.sci_interrupt);
+ return 0;
+}
+
+static void acpi_freeze_restore(void)
+{
+ disable_irq_wake(acpi_gbl_FADT.sci_interrupt);
+ acpi_enable_all_runtime_gpes();
+}
+
static void acpi_freeze_end(void)
{
acpi_scan_lock_release();
@@ -633,6 +647,8 @@ static void acpi_freeze_end(void)
static const struct platform_freeze_ops acpi_freeze_ops = {
.begin = acpi_freeze_begin,
+ .prepare = acpi_freeze_prepare,
+ .restore = acpi_freeze_restore,
.end = acpi_freeze_end,
};
diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c
index 07c8c5a5ee95..834f35c4bf8d 100644
--- a/drivers/acpi/utils.c
+++ b/drivers/acpi/utils.c
@@ -661,7 +661,6 @@ EXPORT_SYMBOL(acpi_evaluate_dsm);
* @uuid: UUID of requested functions, should be 16 bytes at least
* @rev: revision number of requested functions
* @funcs: bitmap of requested functions
- * @exclude: excluding special value, used to support i915 and nouveau
*
* Evaluate device's _DSM method to check whether it supports requested
* functions. Currently only support 64 functions at maximum, should be
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index fcbda105616e..807a88a0f394 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -411,12 +411,6 @@ static int __init video_set_bqc_offset(const struct dmi_system_id *d)
return 0;
}
-static int __init video_set_use_native_backlight(const struct dmi_system_id *d)
-{
- use_native_backlight_dmi = true;
- return 0;
-}
-
static int __init video_disable_native_backlight(const struct dmi_system_id *d)
{
use_native_backlight_dmi = false;
@@ -467,265 +461,6 @@ static struct dmi_system_id video_dmi_table[] __initdata = {
DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 7720"),
},
},
- {
- .callback = video_set_use_native_backlight,
- .ident = "ThinkPad X230",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X230"),
- },
- },
- {
- .callback = video_set_use_native_backlight,
- .ident = "ThinkPad T430 and T430s",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T430"),
- },
- },
- {
- .callback = video_set_use_native_backlight,
- .ident = "ThinkPad T430",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "2349D15"),
- },
- },
- {
- .callback = video_set_use_native_backlight,
- .ident = "ThinkPad T431s",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "20AACTO1WW"),
- },
- },
- {
- .callback = video_set_use_native_backlight,
- .ident = "ThinkPad Edge E530",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "3259A2G"),
- },
- },
- {
- .callback = video_set_use_native_backlight,
- .ident = "ThinkPad Edge E530",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "3259CTO"),
- },
- },
- {
- .callback = video_set_use_native_backlight,
- .ident = "ThinkPad Edge E530",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "3259HJG"),
- },
- },
- {
- .callback = video_set_use_native_backlight,
- .ident = "ThinkPad W530",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad W530"),
- },
- },
- {
- .callback = video_set_use_native_backlight,
- .ident = "ThinkPad X1 Carbon",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X1 Carbon"),
- },
- },
- {
- .callback = video_set_use_native_backlight,
- .ident = "Lenovo Yoga 13",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo IdeaPad Yoga 13"),
- },
- },
- {
- .callback = video_set_use_native_backlight,
- .ident = "Lenovo Yoga 2 11",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Yoga 2 11"),
- },
- },
- {
- .callback = video_set_use_native_backlight,
- .ident = "Thinkpad Helix",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad Helix"),
- },
- },
- {
- .callback = video_set_use_native_backlight,
- .ident = "Dell Inspiron 7520",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7520"),
- },
- },
- {
- .callback = video_set_use_native_backlight,
- .ident = "Acer Aspire 5733Z",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5733Z"),
- },
- },
- {
- .callback = video_set_use_native_backlight,
- .ident = "Acer Aspire 5742G",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5742G"),
- },
- },
- {
- .callback = video_set_use_native_backlight,
- .ident = "Acer Aspire V5-171",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
- DMI_MATCH(DMI_PRODUCT_NAME, "V5-171"),
- },
- },
- {
- .callback = video_set_use_native_backlight,
- .ident = "Acer Aspire V5-431",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Aspire V5-431"),
- },
- },
- {
- .callback = video_set_use_native_backlight,
- .ident = "Acer Aspire V5-471G",
- .matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "Acer"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Aspire V5-471G"),
- },
- },
- {
- .callback = video_set_use_native_backlight,
- .ident = "Acer TravelMate B113",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
- DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate B113"),
- },
- },
- {
- .callback = video_set_use_native_backlight,
- .ident = "Acer Aspire V5-572G",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Acer Aspire"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "V5-572G/Dazzle_CX"),
- },
- },
- {
- .callback = video_set_use_native_backlight,
- .ident = "Acer Aspire V5-573G",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Acer Aspire"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "V5-573G/Dazzle_HW"),
- },
- },
- {
- .callback = video_set_use_native_backlight,
- .ident = "ASUS Zenbook Prime UX31A",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
- DMI_MATCH(DMI_PRODUCT_NAME, "UX31A"),
- },
- },
- {
- .callback = video_set_use_native_backlight,
- .ident = "HP ProBook 4340s",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "HP ProBook 4340s"),
- },
- },
- {
- .callback = video_set_use_native_backlight,
- .ident = "HP ProBook 4540s",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "HP ProBook 4540s"),
- },
- },
- {
- .callback = video_set_use_native_backlight,
- .ident = "HP ProBook 2013 models",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
- DMI_MATCH(DMI_PRODUCT_NAME, "HP ProBook "),
- DMI_MATCH(DMI_PRODUCT_NAME, " G1"),
- },
- },
- {
- .callback = video_set_use_native_backlight,
- .ident = "HP EliteBook 2013 models",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
- DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook "),
- DMI_MATCH(DMI_PRODUCT_NAME, " G1"),
- },
- },
- {
- .callback = video_set_use_native_backlight,
- .ident = "HP EliteBook 2014 models",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
- DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook "),
- DMI_MATCH(DMI_PRODUCT_NAME, " G2"),
- },
- },
- {
- .callback = video_set_use_native_backlight,
- .ident = "HP ZBook 14",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
- DMI_MATCH(DMI_PRODUCT_NAME, "HP ZBook 14"),
- },
- },
- {
- .callback = video_set_use_native_backlight,
- .ident = "HP ZBook 15",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
- DMI_MATCH(DMI_PRODUCT_NAME, "HP ZBook 15"),
- },
- },
- {
- .callback = video_set_use_native_backlight,
- .ident = "HP ZBook 17",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
- DMI_MATCH(DMI_PRODUCT_NAME, "HP ZBook 17"),
- },
- },
- {
- .callback = video_set_use_native_backlight,
- .ident = "HP EliteBook 8470p",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
- DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook 8470p"),
- },
- },
- {
- .callback = video_set_use_native_backlight,
- .ident = "HP EliteBook 8780w",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
- DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook 8780w"),
- },
- },
/*
* These models have a working acpi_video backlight control, and using
@@ -750,6 +485,14 @@ static struct dmi_system_id video_dmi_table[] __initdata = {
DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T520"),
},
},
+ {
+ .callback = video_disable_native_backlight,
+ .ident = "ThinkPad X201s",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X201s"),
+ },
+ },
/* The native backlight controls do not work on some older machines */
{
@@ -1411,6 +1154,23 @@ acpi_video_device_bind(struct acpi_video_bus *video,
}
}
+static bool acpi_video_device_in_dod(struct acpi_video_device *device)
+{
+ struct acpi_video_bus *video = device->video;
+ int i;
+
+ /* If we have a broken _DOD, no need to test */
+ if (!video->attached_count)
+ return true;
+
+ for (i = 0; i < video->attached_count; i++) {
+ if (video->attached_array[i].bind_info == device)
+ return true;
+ }
+
+ return false;
+}
+
/*
* Arg:
* video : video bus device
@@ -1850,6 +1610,15 @@ static void acpi_video_dev_register_backlight(struct acpi_video_device *device)
static int count;
char *name;
+ /*
+ * Do not create backlight device for video output
+ * device that is not in the enumerated list.
+ */
+ if (!acpi_video_device_in_dod(device)) {
+ dev_dbg(&device->dev->dev, "not in _DOD list, ignore\n");
+ return;
+ }
+
result = acpi_video_init_brightness(device);
if (result)
return;
diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c
index c42feb2bacd0..27c43499977a 100644
--- a/drivers/acpi/video_detect.c
+++ b/drivers/acpi/video_detect.c
@@ -174,6 +174,14 @@ static struct dmi_system_id video_detect_dmi_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 5737"),
},
},
+ {
+ .callback = video_detect_force_vendor,
+ .ident = "Lenovo IdeaPad Z570",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "Ideapad Z570"),
+ },
+ },
{ },
};