aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/drivers/acpi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/battery.c4
-rw-r--r--drivers/acpi/ec.c123
-rw-r--r--drivers/acpi/processor_idle.c2
-rw-r--r--drivers/acpi/scan.c388
-rw-r--r--drivers/acpi/sleep.c17
-rw-r--r--drivers/acpi/sleep.h2
-rw-r--r--drivers/acpi/sysfs.c2
7 files changed, 325 insertions, 213 deletions
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index d98ba4355819..baebd1a9b811 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -530,8 +530,8 @@ static int acpi_battery_get_state(struct acpi_battery *battery)
battery->rate_now != ACPI_BATTERY_VALUE_UNKNOWN &&
(s16)(battery->rate_now) < 0) {
battery->rate_now = abs((s16)battery->rate_now);
- printk_once(KERN_WARNING FW_BUG "battery: (dis)charge rate"
- " invalid.\n");
+ printk_once(KERN_WARNING FW_BUG
+ "battery: (dis)charge rate invalid.\n");
}
if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags)
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index a8dd2f763382..220d6406c9e9 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -137,6 +137,50 @@ static int EC_FLAGS_CLEAR_ON_RESUME; /* Needs acpi_ec_clear() on boot/resume */
static int EC_FLAGS_QUERY_HANDSHAKE; /* Needs QR_EC issued when SCI_EVT set */
/* --------------------------------------------------------------------------
+ * Logging/Debugging
+ * -------------------------------------------------------------------------- */
+
+/*
+ * Splitters used by the developers to track the boundary of the EC
+ * handling processes.
+ */
+#ifdef DEBUG
+#define EC_DBG_SEP " "
+#define EC_DBG_DRV "+++++"
+#define EC_DBG_STM "====="
+#define EC_DBG_REQ "*****"
+#define EC_DBG_EVT "#####"
+#else
+#define EC_DBG_SEP ""
+#define EC_DBG_DRV
+#define EC_DBG_STM
+#define EC_DBG_REQ
+#define EC_DBG_EVT
+#endif
+
+#define ec_log_raw(fmt, ...) \
+ pr_info(fmt "\n", ##__VA_ARGS__)
+#define ec_dbg_raw(fmt, ...) \
+ pr_debug(fmt "\n", ##__VA_ARGS__)
+#define ec_log(filter, fmt, ...) \
+ ec_log_raw(filter EC_DBG_SEP fmt EC_DBG_SEP filter, ##__VA_ARGS__)
+#define ec_dbg(filter, fmt, ...) \
+ ec_dbg_raw(filter EC_DBG_SEP fmt EC_DBG_SEP filter, ##__VA_ARGS__)
+
+#define ec_log_drv(fmt, ...) \
+ ec_log(EC_DBG_DRV, fmt, ##__VA_ARGS__)
+#define ec_dbg_drv(fmt, ...) \
+ ec_dbg(EC_DBG_DRV, fmt, ##__VA_ARGS__)
+#define ec_dbg_stm(fmt, ...) \
+ ec_dbg(EC_DBG_STM, fmt, ##__VA_ARGS__)
+#define ec_dbg_req(fmt, ...) \
+ ec_dbg(EC_DBG_REQ, fmt, ##__VA_ARGS__)
+#define ec_dbg_evt(fmt, ...) \
+ ec_dbg(EC_DBG_EVT, fmt, ##__VA_ARGS__)
+#define ec_dbg_ref(ec, fmt, ...) \
+ ec_dbg_raw("%lu: " fmt, ec->reference_count, ## __VA_ARGS__)
+
+/* --------------------------------------------------------------------------
* Device Flags
* -------------------------------------------------------------------------- */
@@ -159,14 +203,14 @@ static inline u8 acpi_ec_read_status(struct acpi_ec *ec)
{
u8 x = inb(ec->command_addr);
- pr_debug("EC_SC(R) = 0x%2.2x "
- "SCI_EVT=%d BURST=%d CMD=%d IBF=%d OBF=%d\n",
- x,
- !!(x & ACPI_EC_FLAG_SCI),
- !!(x & ACPI_EC_FLAG_BURST),
- !!(x & ACPI_EC_FLAG_CMD),
- !!(x & ACPI_EC_FLAG_IBF),
- !!(x & ACPI_EC_FLAG_OBF));
+ ec_dbg_raw("EC_SC(R) = 0x%2.2x "
+ "SCI_EVT=%d BURST=%d CMD=%d IBF=%d OBF=%d",
+ x,
+ !!(x & ACPI_EC_FLAG_SCI),
+ !!(x & ACPI_EC_FLAG_BURST),
+ !!(x & ACPI_EC_FLAG_CMD),
+ !!(x & ACPI_EC_FLAG_IBF),
+ !!(x & ACPI_EC_FLAG_OBF));
return x;
}
@@ -175,20 +219,20 @@ static inline u8 acpi_ec_read_data(struct acpi_ec *ec)
u8 x = inb(ec->data_addr);
ec->curr->timestamp = jiffies;
- pr_debug("EC_DATA(R) = 0x%2.2x\n", x);
+ ec_dbg_raw("EC_DATA(R) = 0x%2.2x", x);
return x;
}
static inline void acpi_ec_write_cmd(struct acpi_ec *ec, u8 command)
{
- pr_debug("EC_SC(W) = 0x%2.2x\n", command);
+ ec_dbg_raw("EC_SC(W) = 0x%2.2x", command);
outb(command, ec->command_addr);
ec->curr->timestamp = jiffies;
}
static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data)
{
- pr_debug("EC_DATA(W) = 0x%2.2x\n", data);
+ ec_dbg_raw("EC_DATA(W) = 0x%2.2x", data);
outb(data, ec->data_addr);
ec->curr->timestamp = jiffies;
}
@@ -240,7 +284,7 @@ static inline void acpi_ec_enable_gpe(struct acpi_ec *ec, bool open)
* software need to manually trigger a pseudo GPE event on
* EN=1 writes.
*/
- pr_debug("***** Polling quirk *****\n");
+ ec_dbg_raw("Polling quirk");
advance_transaction(ec);
}
}
@@ -299,7 +343,7 @@ static void acpi_ec_set_storm(struct acpi_ec *ec, u8 flag)
{
if (!test_bit(flag, &ec->flags)) {
acpi_ec_disable_gpe(ec, false);
- pr_debug("+++++ Polling enabled +++++\n");
+ ec_dbg_drv("Polling enabled");
set_bit(flag, &ec->flags);
}
}
@@ -309,7 +353,7 @@ static void acpi_ec_clear_storm(struct acpi_ec *ec, u8 flag)
if (test_bit(flag, &ec->flags)) {
clear_bit(flag, &ec->flags);
acpi_ec_enable_gpe(ec, false);
- pr_debug("+++++ Polling disabled +++++\n");
+ ec_dbg_drv("Polling disabled");
}
}
@@ -335,7 +379,7 @@ static bool acpi_ec_submit_flushable_request(struct acpi_ec *ec)
static void acpi_ec_submit_query(struct acpi_ec *ec)
{
if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) {
- pr_debug("***** Event started *****\n");
+ ec_dbg_req("Event started");
schedule_work(&ec->work);
}
}
@@ -344,7 +388,7 @@ static void acpi_ec_complete_query(struct acpi_ec *ec)
{
if (ec->curr->command == ACPI_EC_COMMAND_QUERY) {
clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
- pr_debug("***** Event stopped *****\n");
+ ec_dbg_req("Event stopped");
}
}
@@ -366,8 +410,8 @@ static void advance_transaction(struct acpi_ec *ec)
u8 status;
bool wakeup = false;
- pr_debug("===== %s (%d) =====\n",
- in_interrupt() ? "IRQ" : "TASK", smp_processor_id());
+ ec_dbg_stm("%s (%d)", in_interrupt() ? "IRQ" : "TASK",
+ smp_processor_id());
/*
* By always clearing STS before handling all indications, we can
* ensure a hardware STS 0->1 change after this clearing can always
@@ -390,8 +434,8 @@ static void advance_transaction(struct acpi_ec *ec)
if (t->rlen == t->ri) {
t->flags |= ACPI_EC_COMMAND_COMPLETE;
if (t->command == ACPI_EC_COMMAND_QUERY)
- pr_debug("***** Command(%s) hardware completion *****\n",
- acpi_ec_cmd_string(t->command));
+ ec_dbg_req("Command(%s) hardware completion",
+ acpi_ec_cmd_string(t->command));
wakeup = true;
}
} else
@@ -410,8 +454,8 @@ static void advance_transaction(struct acpi_ec *ec)
acpi_ec_complete_query(ec);
t->rdata[t->ri++] = 0x00;
t->flags |= ACPI_EC_COMMAND_COMPLETE;
- pr_debug("***** Command(%s) software completion *****\n",
- acpi_ec_cmd_string(t->command));
+ ec_dbg_req("Command(%s) software completion",
+ acpi_ec_cmd_string(t->command));
wakeup = true;
} else if ((status & ACPI_EC_FLAG_IBF) == 0) {
acpi_ec_write_cmd(ec, t->command);
@@ -502,21 +546,21 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec,
ret = -EINVAL;
goto unlock;
}
+ ec_dbg_ref(ec, "Increase command");
/* following two actions should be kept atomic */
ec->curr = t;
- pr_debug("***** Command(%s) started *****\n",
- acpi_ec_cmd_string(t->command));
+ ec_dbg_req("Command(%s) started", acpi_ec_cmd_string(t->command));
start_transaction(ec);
spin_unlock_irqrestore(&ec->lock, tmp);
ret = ec_poll(ec);
spin_lock_irqsave(&ec->lock, tmp);
if (t->irq_count == ec_storm_threshold)
acpi_ec_clear_storm(ec, EC_FLAGS_COMMAND_STORM);
- pr_debug("***** Command(%s) stopped *****\n",
- acpi_ec_cmd_string(t->command));
+ ec_dbg_req("Command(%s) stopped", acpi_ec_cmd_string(t->command));
ec->curr = NULL;
/* Disable GPE for command processing (IBF=0/OBF=1) */
acpi_ec_complete_request(ec);
+ ec_dbg_ref(ec, "Decrease command");
unlock:
spin_unlock_irqrestore(&ec->lock, tmp);
return ret;
@@ -676,11 +720,13 @@ static void acpi_ec_start(struct acpi_ec *ec, bool resuming)
spin_lock_irqsave(&ec->lock, flags);
if (!test_and_set_bit(EC_FLAGS_STARTED, &ec->flags)) {
- pr_debug("+++++ Starting EC +++++\n");
+ ec_dbg_drv("Starting EC");
/* Enable GPE for event processing (SCI_EVT=1) */
- if (!resuming)
+ if (!resuming) {
acpi_ec_submit_request(ec);
- pr_debug("EC started\n");
+ ec_dbg_ref(ec, "Increase driver");
+ }
+ ec_log_drv("EC started");
}
spin_unlock_irqrestore(&ec->lock, flags);
}
@@ -702,17 +748,19 @@ static void acpi_ec_stop(struct acpi_ec *ec, bool suspending)
spin_lock_irqsave(&ec->lock, flags);
if (acpi_ec_started(ec)) {
- pr_debug("+++++ Stopping EC +++++\n");
+ ec_dbg_drv("Stopping EC");
set_bit(EC_FLAGS_STOPPED, &ec->flags);
spin_unlock_irqrestore(&ec->lock, flags);
wait_event(ec->wait, acpi_ec_stopped(ec));
spin_lock_irqsave(&ec->lock, flags);
/* Disable GPE for event processing (SCI_EVT=1) */
- if (!suspending)
+ if (!suspending) {
acpi_ec_complete_request(ec);
+ ec_dbg_ref(ec, "Decrease driver");
+ }
clear_bit(EC_FLAGS_STARTED, &ec->flags);
clear_bit(EC_FLAGS_STOPPED, &ec->flags);
- pr_debug("EC stopped\n");
+ ec_log_drv("EC stopped");
}
spin_unlock_irqrestore(&ec->lock, flags);
}
@@ -824,12 +872,12 @@ static void acpi_ec_run(void *cxt)
if (!handler)
return;
- pr_debug("##### Query(0x%02x) started #####\n", handler->query_bit);
+ ec_dbg_evt("Query(0x%02x) started", handler->query_bit);
if (handler->func)
handler->func(handler->data);
else if (handler->handle)
acpi_evaluate_object(handler->handle, NULL, NULL, NULL);
- pr_debug("##### Query(0x%02x) stopped #####\n", handler->query_bit);
+ ec_dbg_evt("Query(0x%02x) stopped", handler->query_bit);
acpi_ec_put_query_handler(handler);
}
@@ -861,8 +909,8 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 *data)
if (value == handler->query_bit) {
/* have custom handler for this bit */
handler = acpi_ec_get_query_handler(handler);
- pr_debug("##### Query(0x%02x) scheduled #####\n",
- handler->query_bit);
+ ec_dbg_evt("Query(0x%02x) scheduled",
+ handler->query_bit);
status = acpi_os_execute((handler->func) ?
OSL_NOTIFY_HANDLER : OSL_GPE_HANDLER,
acpi_ec_run, handler);
@@ -1099,6 +1147,9 @@ static int acpi_ec_add(struct acpi_device *device)
ret = ec_install_handlers(ec);
+ /* Reprobe devices depending on the EC */
+ acpi_walk_dep_device_list(ec->handle);
+
/* EC is fully operational, allow queries */
clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index c6bb9f1257c9..f98db0b50551 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -922,7 +922,7 @@ static int acpi_processor_setup_cpuidle_states(struct acpi_processor *pr)
return -EINVAL;
drv->safe_state_index = -1;
- for (i = 0; i < CPUIDLE_STATE_MAX; i++) {
+ for (i = CPUIDLE_DRIVER_STATE_START; i < CPUIDLE_STATE_MAX; i++) {
drv->states[i].name[0] = '\0';
drv->states[i].desc[0] = '\0';
}
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index bbca7830e18a..d2e3c3e3f9c9 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -114,7 +114,12 @@ int acpi_scan_add_handler_with_hotplug(struct acpi_scan_handler *handler,
return 0;
}
-/*
+/**
+ * create_pnp_modalias - Create hid/cid(s) string for modalias and uevent
+ * @acpi_dev: ACPI device object.
+ * @modalias: Buffer to print into.
+ * @size: Size of the buffer.
+ *
* Creates hid/cid(s) string needed for modalias and uevent
* e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get:
* char *modalias: "acpi:IBM0001:ACPI0001"
@@ -122,68 +127,98 @@ int acpi_scan_add_handler_with_hotplug(struct acpi_scan_handler *handler,
* -EINVAL: output error
* -ENOMEM: output is truncated
*/
-static int create_modalias(struct acpi_device *acpi_dev, char *modalias,
- int size)
+static int create_pnp_modalias(struct acpi_device *acpi_dev, char *modalias,
+ int size)
{
int len;
int count;
struct acpi_hardware_id *id;
- if (list_empty(&acpi_dev->pnp.ids))
- return 0;
-
/*
- * If the device has PRP0001 we expose DT compatible modalias
- * instead in form of of:NnameTCcompatible.
+ * Since we skip PRP0001 from the modalias below, 0 should be returned
+ * if PRP0001 is the only ACPI/PNP ID in the device's list.
*/
- if (acpi_dev->data.of_compatible) {
- struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
- const union acpi_object *of_compatible, *obj;
- int i, nval;
- char *c;
-
- acpi_get_name(acpi_dev->handle, ACPI_SINGLE_NAME, &buf);
- /* DT strings are all in lower case */
- for (c = buf.pointer; *c != '\0'; c++)
- *c = tolower(*c);
-
- len = snprintf(modalias, size, "of:N%sT", (char *)buf.pointer);
- ACPI_FREE(buf.pointer);
-
- of_compatible = acpi_dev->data.of_compatible;
- if (of_compatible->type == ACPI_TYPE_PACKAGE) {
- nval = of_compatible->package.count;
- obj = of_compatible->package.elements;
- } else { /* Must be ACPI_TYPE_STRING. */
- nval = 1;
- obj = of_compatible;
- }
- for (i = 0; i < nval; i++, obj++) {
- count = snprintf(&modalias[len], size, "C%s",
- obj->string.pointer);
- if (count < 0)
- return -EINVAL;
- if (count >= size)
- return -ENOMEM;
-
- len += count;
- size -= count;
- }
- } else {
- len = snprintf(modalias, size, "acpi:");
- size -= len;
+ count = 0;
+ list_for_each_entry(id, &acpi_dev->pnp.ids, list)
+ if (strcmp(id->id, "PRP0001"))
+ count++;
- list_for_each_entry(id, &acpi_dev->pnp.ids, list) {
- count = snprintf(&modalias[len], size, "%s:", id->id);
- if (count < 0)
- return -EINVAL;
- if (count >= size)
- return -ENOMEM;
- len += count;
- size -= count;
- }
+ if (!count)
+ return 0;
+
+ len = snprintf(modalias, size, "acpi:");
+ if (len <= 0)
+ return len;
+
+ size -= len;
+
+ list_for_each_entry(id, &acpi_dev->pnp.ids, list) {
+ if (!strcmp(id->id, "PRP0001"))
+ continue;
+
+ count = snprintf(&modalias[len], size, "%s:", id->id);
+ if (count < 0)
+ return -EINVAL;
+
+ if (count >= size)
+ return -ENOMEM;
+
+ len += count;
+ size -= count;
}
+ modalias[len] = '\0';
+ return len;
+}
+/**
+ * create_of_modalias - Creates DT compatible string for modalias and uevent
+ * @acpi_dev: ACPI device object.
+ * @modalias: Buffer to print into.
+ * @size: Size of the buffer.
+ *
+ * Expose DT compatible modalias as of:NnameTCcompatible. This function should
+ * only be called for devices having PRP0001 in their list of ACPI/PNP IDs.
+ */
+static int create_of_modalias(struct acpi_device *acpi_dev, char *modalias,
+ int size)
+{
+ struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
+ const union acpi_object *of_compatible, *obj;
+ int len, count;
+ int i, nval;
+ char *c;
+
+ acpi_get_name(acpi_dev->handle, ACPI_SINGLE_NAME, &buf);
+ /* DT strings are all in lower case */
+ for (c = buf.pointer; *c != '\0'; c++)
+ *c = tolower(*c);
+
+ len = snprintf(modalias, size, "of:N%sT", (char *)buf.pointer);
+ ACPI_FREE(buf.pointer);
+
+ if (len <= 0)
+ return len;
+
+ of_compatible = acpi_dev->data.of_compatible;
+ if (of_compatible->type == ACPI_TYPE_PACKAGE) {
+ nval = of_compatible->package.count;
+ obj = of_compatible->package.elements;
+ } else { /* Must be ACPI_TYPE_STRING. */
+ nval = 1;
+ obj = of_compatible;
+ }
+ for (i = 0; i < nval; i++, obj++) {
+ count = snprintf(&modalias[len], size, "C%s",
+ obj->string.pointer);
+ if (count < 0)
+ return -EINVAL;
+
+ if (count >= size)
+ return -ENOMEM;
+
+ len += count;
+ size -= count;
+ }
modalias[len] = '\0';
return len;
}
@@ -194,7 +229,8 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias,
*
* Check if the given device has an ACPI companion and if that companion has
* a valid list of PNP IDs, and if the device is the first (primary) physical
- * device associated with it.
+ * device associated with it. Return the companion pointer if that's the case
+ * or NULL otherwise.
*
* If multiple physical devices are attached to a single ACPI companion, we need
* to be careful. The usage scenario for this kind of relationship is that all
@@ -208,88 +244,127 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias,
* resources available from it but they will be matched normally using functions
* provided by their bus types (and analogously for their modalias).
*/
-static bool acpi_companion_match(const struct device *dev)
+static struct acpi_device *acpi_companion_match(const struct device *dev)
{
struct acpi_device *adev;
- bool ret;
adev = ACPI_COMPANION(dev);
if (!adev)
- return false;
+ return NULL;
if (list_empty(&adev->pnp.ids))
- return false;
+ return NULL;
mutex_lock(&adev->physical_node_lock);
if (list_empty(&adev->physical_node_list)) {
- ret = false;
+ adev = NULL;
} else {
const struct acpi_device_physical_node *node;
node = list_first_entry(&adev->physical_node_list,
struct acpi_device_physical_node, node);
- ret = node->dev == dev;
+ if (node->dev != dev)
+ adev = NULL;
}
mutex_unlock(&adev->physical_node_lock);
- return ret;
+ return adev;
}
-/*
- * Creates uevent modalias field for ACPI enumerated devices.
- * Because the other buses does not support ACPI HIDs & CIDs.
- * e.g. for a device with hid:IBM0001 and cid:ACPI0001 you get:
- * "acpi:IBM0001:ACPI0001"
- */
-int acpi_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env)
+static int __acpi_device_uevent_modalias(struct acpi_device *adev,
+ struct kobj_uevent_env *env)
{
int len;
- if (!acpi_companion_match(dev))
+ if (!adev)
return -ENODEV;
+ if (list_empty(&adev->pnp.ids))
+ return 0;
+
if (add_uevent_var(env, "MODALIAS="))
return -ENOMEM;
- len = create_modalias(ACPI_COMPANION(dev), &env->buf[env->buflen - 1],
- sizeof(env->buf) - env->buflen);
- if (len <= 0)
+
+ len = create_pnp_modalias(adev, &env->buf[env->buflen - 1],
+ sizeof(env->buf) - env->buflen);
+ if (len < 0)
+ return len;
+
+ env->buflen += len;
+ if (!adev->data.of_compatible)
+ return 0;
+
+ if (len > 0 && add_uevent_var(env, "MODALIAS="))
+ return -ENOMEM;
+
+ len = create_of_modalias(adev, &env->buf[env->buflen - 1],
+ sizeof(env->buf) - env->buflen);
+ if (len < 0)
return len;
+
env->buflen += len;
+
return 0;
}
-EXPORT_SYMBOL_GPL(acpi_device_uevent_modalias);
/*
- * Creates modalias sysfs attribute for ACPI enumerated devices.
+ * Creates uevent modalias field for ACPI enumerated devices.
* Because the other buses does not support ACPI HIDs & CIDs.
* e.g. for a device with hid:IBM0001 and cid:ACPI0001 you get:
* "acpi:IBM0001:ACPI0001"
*/
-int acpi_device_modalias(struct device *dev, char *buf, int size)
+int acpi_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env)
{
- int len;
+ return __acpi_device_uevent_modalias(acpi_companion_match(dev), env);
+}
+EXPORT_SYMBOL_GPL(acpi_device_uevent_modalias);
+
+static int __acpi_device_modalias(struct acpi_device *adev, char *buf, int size)
+{
+ int len, count;
- if (!acpi_companion_match(dev))
+ if (!adev)
return -ENODEV;
- len = create_modalias(ACPI_COMPANION(dev), buf, size -1);
- if (len <= 0)
+ if (list_empty(&adev->pnp.ids))
+ return 0;
+
+ len = create_pnp_modalias(adev, buf, size - 1);
+ if (len < 0) {
+ return len;
+ } else if (len > 0) {
+ buf[len++] = '\n';
+ size -= len;
+ }
+ if (!adev->data.of_compatible)
return len;
- buf[len++] = '\n';
+
+ count = create_of_modalias(adev, buf + len, size - 1);
+ if (count < 0) {
+ return count;
+ } else if (count > 0) {
+ len += count;
+ buf[len++] = '\n';
+ }
+
return len;
}
+
+/*
+ * Creates modalias sysfs attribute for ACPI enumerated devices.
+ * Because the other buses does not support ACPI HIDs & CIDs.
+ * e.g. for a device with hid:IBM0001 and cid:ACPI0001 you get:
+ * "acpi:IBM0001:ACPI0001"
+ */
+int acpi_device_modalias(struct device *dev, char *buf, int size)
+{
+ return __acpi_device_modalias(acpi_companion_match(dev), buf, size);
+}
EXPORT_SYMBOL_GPL(acpi_device_modalias);
static ssize_t
acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, char *buf) {
- struct acpi_device *acpi_dev = to_acpi_device(dev);
- int len;
-
- len = create_modalias(acpi_dev, buf, 1024);
- if (len <= 0)
- return len;
- buf[len++] = '\n';
- return len;
+ return __acpi_device_modalias(to_acpi_device(dev), buf, 1024);
}
static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL);
@@ -894,8 +969,51 @@ static void acpi_device_remove_files(struct acpi_device *dev)
ACPI Bus operations
-------------------------------------------------------------------------- */
+/**
+ * acpi_of_match_device - Match device object using the "compatible" property.
+ * @adev: ACPI device object to match.
+ * @of_match_table: List of device IDs to match against.
+ *
+ * If @dev has an ACPI companion which has the special PRP0001 device ID in its
+ * list of identifiers and a _DSD object with the "compatible" property, use
+ * that property to match against the given list of identifiers.
+ */
+static bool acpi_of_match_device(struct acpi_device *adev,
+ const struct of_device_id *of_match_table)
+{
+ const union acpi_object *of_compatible, *obj;
+ int i, nval;
+
+ if (!adev)
+ return false;
+
+ of_compatible = adev->data.of_compatible;
+ if (!of_match_table || !of_compatible)
+ return false;
+
+ if (of_compatible->type == ACPI_TYPE_PACKAGE) {
+ nval = of_compatible->package.count;
+ obj = of_compatible->package.elements;
+ } else { /* Must be ACPI_TYPE_STRING. */
+ nval = 1;
+ obj = of_compatible;
+ }
+ /* Now we can look for the driver DT compatible strings */
+ for (i = 0; i < nval; i++, obj++) {
+ const struct of_device_id *id;
+
+ for (id = of_match_table; id->compatible[0]; id++)
+ if (!strcasecmp(obj->string.pointer, id->compatible))
+ return true;
+ }
+
+ return false;
+}
+
static const struct acpi_device_id *__acpi_match_device(
- struct acpi_device *device, const struct acpi_device_id *ids)
+ struct acpi_device *device,
+ const struct acpi_device_id *ids,
+ const struct of_device_id *of_ids)
{
const struct acpi_device_id *id;
struct acpi_hardware_id *hwid;
@@ -904,14 +1022,27 @@ static const struct acpi_device_id *__acpi_match_device(
* If the device is not present, it is unnecessary to load device
* driver for it.
*/
- if (!device->status.present)
+ if (!device || !device->status.present)
return NULL;
- for (id = ids; id->id[0]; id++)
- list_for_each_entry(hwid, &device->pnp.ids, list)
+ list_for_each_entry(hwid, &device->pnp.ids, list) {
+ /* First, check the ACPI/PNP IDs provided by the caller. */
+ for (id = ids; id->id[0]; id++)
if (!strcmp((char *) id->id, hwid->id))
return id;
+ /*
+ * Next, check the special "PRP0001" ID and try to match the
+ * "compatible" property if found.
+ *
+ * The id returned by the below is not valid, but the only
+ * caller passing non-NULL of_ids here is only interested in
+ * whether or not the return value is NULL.
+ */
+ if (!strcmp("PRP0001", hwid->id)
+ && acpi_of_match_device(device, of_ids))
+ return id;
+ }
return NULL;
}
@@ -929,68 +1060,26 @@ static const struct acpi_device_id *__acpi_match_device(
const struct acpi_device_id *acpi_match_device(const struct acpi_device_id *ids,
const struct device *dev)
{
- struct acpi_device *adev;
- acpi_handle handle = ACPI_HANDLE(dev);
-
- if (!ids || !handle || acpi_bus_get_device(handle, &adev))
- return NULL;
-
- if (!acpi_companion_match(dev))
- return NULL;
-
- return __acpi_match_device(adev, ids);
+ return __acpi_match_device(acpi_companion_match(dev), ids, NULL);
}
EXPORT_SYMBOL_GPL(acpi_match_device);
int acpi_match_device_ids(struct acpi_device *device,
const struct acpi_device_id *ids)
{
- return __acpi_match_device(device, ids) ? 0 : -ENOENT;
+ return __acpi_match_device(device, ids, NULL) ? 0 : -ENOENT;
}
EXPORT_SYMBOL(acpi_match_device_ids);
-/* Performs match against special "PRP0001" shoehorn ACPI ID */
-static bool acpi_of_driver_match_device(struct device *dev,
- const struct device_driver *drv)
-{
- const union acpi_object *of_compatible, *obj;
- struct acpi_device *adev;
- int i, nval;
-
- adev = ACPI_COMPANION(dev);
- if (!adev)
- return false;
-
- of_compatible = adev->data.of_compatible;
- if (!drv->of_match_table || !of_compatible)
- return false;
-
- if (of_compatible->type == ACPI_TYPE_PACKAGE) {
- nval = of_compatible->package.count;
- obj = of_compatible->package.elements;
- } else { /* Must be ACPI_TYPE_STRING. */
- nval = 1;
- obj = of_compatible;
- }
- /* Now we can look for the driver DT compatible strings */
- for (i = 0; i < nval; i++, obj++) {
- const struct of_device_id *id;
-
- for (id = drv->of_match_table; id->compatible[0]; id++)
- if (!strcasecmp(obj->string.pointer, id->compatible))
- return true;
- }
-
- return false;
-}
-
bool acpi_driver_match_device(struct device *dev,
const struct device_driver *drv)
{
if (!drv->acpi_match_table)
- return acpi_of_driver_match_device(dev, drv);
+ return acpi_of_match_device(ACPI_COMPANION(dev),
+ drv->of_match_table);
- return !!acpi_match_device(drv->acpi_match_table, dev);
+ return !!__acpi_match_device(acpi_companion_match(dev),
+ drv->acpi_match_table, drv->of_match_table);
}
EXPORT_SYMBOL_GPL(acpi_driver_match_device);
@@ -1031,20 +1120,7 @@ static int acpi_bus_match(struct device *dev, struct device_driver *drv)
static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env)
{
- struct acpi_device *acpi_dev = to_acpi_device(dev);
- int len;
-
- if (list_empty(&acpi_dev->pnp.ids))
- return 0;
-
- if (add_uevent_var(env, "MODALIAS="))
- return -ENOMEM;
- len = create_modalias(acpi_dev, &env->buf[env->buflen - 1],
- sizeof(env->buf) - env->buflen);
- if (len <= 0)
- return len;
- env->buflen += len;
- return 0;
+ return __acpi_device_uevent_modalias(to_acpi_device(dev), env);
}
static void acpi_device_notify(acpi_handle handle, u32 event, void *data)
@@ -1062,10 +1138,10 @@ static void acpi_device_notify_fixed(void *data)
acpi_device_notify(NULL, ACPI_FIXED_HARDWARE_EVENT, device);
}
-static acpi_status acpi_device_fixed_event(void *data)
+static u32 acpi_device_fixed_event(void *data)
{
acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_device_notify_fixed, data);
- return AE_OK;
+ return ACPI_INTERRUPT_HANDLED;
}
static int acpi_device_install_notify_handler(struct acpi_device *device)
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index 7f251dd1a687..2f0d4db40a9e 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -629,6 +629,7 @@ static int acpi_freeze_begin(void)
static int acpi_freeze_prepare(void)
{
+ acpi_enable_wakeup_devices(ACPI_STATE_S0);
acpi_enable_all_wakeup_gpes();
acpi_os_wait_events_complete();
enable_irq_wake(acpi_gbl_FADT.sci_interrupt);
@@ -637,6 +638,7 @@ static int acpi_freeze_prepare(void)
static void acpi_freeze_restore(void)
{
+ acpi_disable_wakeup_devices(ACPI_STATE_S0);
disable_irq_wake(acpi_gbl_FADT.sci_interrupt);
acpi_enable_all_runtime_gpes();
}
@@ -806,21 +808,6 @@ static void acpi_sleep_hibernate_setup(void)
static inline void acpi_sleep_hibernate_setup(void) {}
#endif /* !CONFIG_HIBERNATION */
-int acpi_suspend(u32 acpi_state)
-{
- suspend_state_t states[] = {
- [1] = PM_SUSPEND_STANDBY,
- [3] = PM_SUSPEND_MEM,
- [5] = PM_SUSPEND_MAX
- };
-
- if (acpi_state < 6 && states[acpi_state])
- return pm_suspend(states[acpi_state]);
- if (acpi_state == 4)
- return hibernate();
- return -EINVAL;
-}
-
static void acpi_power_off_prepare(void)
{
/* Prepare to power off the system */
diff --git a/drivers/acpi/sleep.h b/drivers/acpi/sleep.h
index 0143540a2519..c797ffa568d5 100644
--- a/drivers/acpi/sleep.h
+++ b/drivers/acpi/sleep.h
@@ -1,6 +1,4 @@
-extern int acpi_suspend(u32 state);
-
extern void acpi_enable_wakeup_devices(u8 sleep_state);
extern void acpi_disable_wakeup_devices(u8 sleep_state);
diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c
index 13e577c80201..0876d77b3206 100644
--- a/drivers/acpi/sysfs.c
+++ b/drivers/acpi/sysfs.c
@@ -527,7 +527,7 @@ static ssize_t counter_show(struct kobject *kobj,
acpi_irq_not_handled;
all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_GPE].count =
acpi_gpe_count;
- size = sprintf(buf, "%8d", all_counters[index].count);
+ size = sprintf(buf, "%8u", all_counters[index].count);
/* "gpe_all" or "sci" */
if (index >= num_gpes + ACPI_NUM_FIXED_EVENTS)