/* * The SCI_EVT clearing timing is not defined by the ACPI specification. * This leads to lots of practical timing issues for the host EC driver. * The following variations are defined (from the target EC firmware's * perspective): * STATUS: After indicating SCI_EVT edge triggered IRQ to the host, the * target can clear SCI_EVT at any time so long as the host can see * the indication by reading the status register (EC_SC). So the * host should re-check SCI_EVT after the first time the SCI_EVT * indication is seen, which is the same time the query request * (QR_EC) is written to the command register (EC_CMD). SCI_EVT set * at any later time could indicate another event. Normally such * kind of EC firmware has implemented an event queue and will * return 0x00 to indicate "no outstanding event". * QUERY: After seeing the query request (QR_EC) written to the command * register (EC_CMD) by the host and having prepared the responding * event value in the data register (EC_DATA), the target can safely * clear SCI_EVT because the target can confirm that the current * event is being handled by the host. The host then should check * SCI_EVT right after reading the event response from the data * register (EC_DATA). * EVENT: After seeing the event response read from the data register * (EC_DATA) by the host, the target can clear SCI_EVT. As the * target requires time to notice the change in the data register * (EC_DATA), the host may be required to wait additional guarding * time before checking the SCI_EVT again. Such guarding may not be * necessary if the host is notified via another IRQ.
*/ #define ACPI_EC_EVT_TIMING_STATUS 0x00 #define ACPI_EC_EVT_TIMING_QUERY 0x01 #define ACPI_EC_EVT_TIMING_EVENT 0x02
#define ACPI_EC_DELAY 500 /* Wait 500ms max. during EC ops */ #define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ #define ACPI_EC_UDELAY_POLL 550 /* Wait 1ms for EC transaction polling */ #define ACPI_EC_CLEAR_MAX 100 /* Maximum number of events to query
* when trying to clear the EC */ #define ACPI_EC_MAX_QUERIES 16 /* Maximum number of parallel queries */
#define ACPI_EC_COMMAND_POLL 0x01 /* Available for command byte */ #define ACPI_EC_COMMAND_COMPLETE 0x02 /* Completed last byte */
/* ec.c is compiled in acpi namespace so this shows up as acpi.ec_delay param */ staticunsignedint ec_delay __read_mostly = ACPI_EC_DELAY;
module_param(ec_delay, uint, 0644);
MODULE_PARM_DESC(ec_delay, "Timeout(ms) waited until an EC command completes");
/* * If the number of false interrupts per one transaction exceeds * this threshold, will think there is a GPE storm happened and * will disable the GPE for normal transaction.
*/ staticunsignedint ec_storm_threshold __read_mostly = 8;
module_param(ec_storm_threshold, uint, 0644);
MODULE_PARM_DESC(ec_storm_threshold, "Maxim false GPE numbers not considered as GPE storm");
staticbool acpi_ec_event_enabled(struct acpi_ec *ec)
{ /* * There is an OSPM early stage logic. During the early stages * (boot/resume), OSPMs shouldn't enable the event handling, only * the EC transactions are allowed to be performed.
*/ if (!test_bit(EC_FLAGS_QUERY_ENABLED, &ec->flags)) returnfalse; /* * However, disabling the event handling is experimental for late * stage (suspend), and is controlled by the boot parameter of * "ec_freeze_events": * 1. true: The EC event handling is disabled before entering * the noirq stage. * 2. false: The EC event handling is automatically disabled as * soon as the EC driver is stopped.
*/ if (ec_freeze_events) return acpi_ec_started(ec); else return test_bit(EC_FLAGS_STARTED, &ec->flags);
}
staticvoid acpi_ec_unmask_events(struct acpi_ec *ec)
{ if (test_bit(EC_FLAGS_EVENTS_MASKED, &ec->flags)) {
clear_bit(EC_FLAGS_EVENTS_MASKED, &ec->flags); if (ec->gpe >= 0)
acpi_ec_enable_gpe(ec, false); else
enable_irq(ec->irq);
ec_dbg_drv("Polling disabled");
}
}
/* * acpi_ec_submit_flushable_request() - Increase the reference count unless * the flush operation is not in * progress * @ec: the EC device * * This function must be used before taking a new action that should hold * the reference count. If this function returns false, then the action * must be discarded or it will prevent the flush operation from being * completed.
*/ staticbool acpi_ec_submit_flushable_request(struct acpi_ec *ec)
{ if (!acpi_ec_started(ec)) returnfalse;
acpi_ec_submit_request(ec); returntrue;
}
staticvoid acpi_ec_submit_event(struct acpi_ec *ec)
{ /* * It is safe to mask the events here, because acpi_ec_close_event() * will run at least once after this.
*/
acpi_ec_mask_events(ec); if (!acpi_ec_event_enabled(ec)) return;
ec->event_state = EC_EVENT_IN_PROGRESS; /* * If events_to_process is greater than 0 at this point, the while () * loop in acpi_ec_event_handler() is still running and incrementing * events_to_process will cause it to invoke acpi_ec_submit_query() once * more, so it is not necessary to queue up the event work to start the * same loop again.
*/ if (ec->events_to_process++ > 0) return;
staticinlinevoid __acpi_ec_enable_event(struct acpi_ec *ec)
{ if (!test_and_set_bit(EC_FLAGS_QUERY_ENABLED, &ec->flags))
ec_log_drv("event unblocked"); /* * Unconditionally invoke this once after enabling the event * handling mechanism to detect the pending events.
*/
advance_transaction(ec, false);
}
/* * Process _Q events that might have accumulated in the EC. * Run with locked ec mutex.
*/ staticvoid acpi_ec_clear(struct acpi_ec *ec)
{ int i;
for (i = 0; i < ACPI_EC_CLEAR_MAX; i++) { if (acpi_ec_submit_query(ec)) break;
} if (unlikely(i == ACPI_EC_CLEAR_MAX))
pr_warn("Warning: Maximum of %d stale EC events cleared\n", i); else
pr_info("%d stale EC events cleared\n", i);
}
spin_lock_irqsave(&ec->lock, flags); /* * If firmware SCI_EVT clearing timing is "event", we actually * don't know when the SCI_EVT will be cleared by firmware after * evaluating _Qxx, so we need to re-check SCI_EVT after waiting an * acceptable period. * * The guarding period is applicable if the event state is not * EC_EVENT_READY, but otherwise if the current transaction is of the * ACPI_EC_COMMAND_QUERY type, the guarding should have elapsed already * and it should not be applied to let the transaction transition into * the ACPI_EC_COMMAND_POLL state immediately.
*/
guarded = ec_event_clearing == ACPI_EC_EVT_TIMING_EVENT &&
ec->event_state != EC_EVENT_READY &&
(!ec->curr || ec->curr->command != ACPI_EC_COMMAND_QUERY);
spin_unlock_irqrestore(&ec->lock, flags); return guarded;
}
staticint ec_transaction_polled(struct acpi_ec *ec)
{ unsignedlong flags; int ret = 0;
spin_lock_irqsave(&ec->lock, flags); if (ec->curr && (ec->curr->flags & ACPI_EC_COMMAND_POLL))
ret = 1;
spin_unlock_irqrestore(&ec->lock, flags); return ret;
}
staticint ec_transaction_completed(struct acpi_ec *ec)
{ unsignedlong flags; int ret = 0;
spin_lock_irqsave(&ec->lock, flags); if (ec->curr && (ec->curr->flags & ACPI_EC_COMMAND_COMPLETE))
ret = 1;
spin_unlock_irqrestore(&ec->lock, flags); return ret;
}
/* * Another IRQ or a guarded polling mode advancement is detected, * the next QR_EC submission is then allowed.
*/ if (!t || !(t->flags & ACPI_EC_COMMAND_POLL)) { if (ec_event_clearing == ACPI_EC_EVT_TIMING_EVENT &&
ec->event_state == EC_EVENT_COMPLETE)
acpi_ec_close_event(ec);
/* Ensure guarding period before polling EC status */ do { if (ec->busy_polling) { /* Perform busy polling */ if (ec_transaction_completed(ec)) return 0;
udelay(jiffies_to_usecs(guard));
} else { /* * Perform wait polling * 1. Wait the transaction to be completed by the * GPE handler after the transaction enters * ACPI_EC_COMMAND_POLL state. * 2. A special guarding logic is also required * for event clearing mode "event" before the * transaction enters ACPI_EC_COMMAND_POLL * state.
*/ if (!ec_transaction_polled(ec) &&
!acpi_ec_guard_event(ec)) break; if (wait_event_timeout(ec->wait,
ec_transaction_completed(ec),
guard)) return 0;
}
} while (time_before(jiffies, timeout)); return -ETIME;
}
staticint ec_poll(struct acpi_ec *ec)
{ unsignedlong flags; int repeat = 5; /* number of command restarts */
while (repeat--) { unsignedlong delay = jiffies +
msecs_to_jiffies(ec_delay); do { if (!ec_guard(ec)) return 0;
spin_lock_irqsave(&ec->lock, flags);
advance_transaction(ec, false);
spin_unlock_irqrestore(&ec->lock, flags);
} while (time_before(jiffies, delay));
pr_debug("controller reset, restart transaction\n");
spin_lock_irqsave(&ec->lock, flags);
start_transaction(ec);
spin_unlock_irqrestore(&ec->lock, flags);
} return -ETIME;
}
staticint acpi_ec_transaction_unlocked(struct acpi_ec *ec, struct transaction *t)
{ unsignedlong tmp; int ret = 0;
if (t->rdata)
memset(t->rdata, 0, t->rlen);
/* start transaction */
spin_lock_irqsave(&ec->lock, tmp); /* Enable GPE for command processing (IBF=0/OBF=1) */ if (!acpi_ec_submit_flushable_request(ec)) {
ret = -EINVAL; goto unlock;
}
ec_dbg_ref(ec, "Increase command"); /* following two actions should be kept atomic */
ec->curr = t;
ec_dbg_req("Command(%s) started", acpi_ec_cmd_string(t->command));
start_transaction(ec);
spin_unlock_irqrestore(&ec->lock, tmp);
mutex_lock(&ec->mutex); if (ec->global_lock) {
status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); if (ACPI_FAILURE(status)) {
status = -ENODEV; goto unlock;
}
}
status = acpi_ec_transaction_unlocked(ec, t);
if (ec->global_lock)
acpi_release_global_lock(glk);
unlock:
mutex_unlock(&ec->mutex); return status;
}
/* Get the handle to the EC device */
acpi_handle ec_get_handle(void)
{ if (!first_ec) return NULL; return first_ec->handle;
}
EXPORT_SYMBOL(ec_get_handle);
mutex_lock(&ec->mutex); /* Prevent transactions from being carried out */
acpi_ec_stop(ec, true);
mutex_unlock(&ec->mutex);
}
void acpi_ec_unblock_transactions(void)
{ /* * Allow transactions to happen again (this function is called from * atomic context during wakeup, so we don't need to acquire the mutex).
*/ if (first_ec)
acpi_ec_start(first_ec, true);
}
mutex_lock(&ec->mutex);
list_for_each_entry_safe(handler, tmp, &ec->list, node) { /* * When remove_all is false, only remove custom query handlers * which have handler->func set. This is done to preserve query * handlers discovered thru ACPI, as they should continue handling * EC queries.
*/ if (remove_all || (handler->func && handler->query_bit == query_bit)) {
list_del_init(&handler->node);
list_add(&handler->node, &free_list);
staticint acpi_ec_submit_query(struct acpi_ec *ec)
{ struct acpi_ec_query *q;
u8 value = 0; int result;
q = acpi_ec_create_query(ec, &value); if (!q) return -ENOMEM;
/* * Query the EC to find out which _Qxx method we need to evaluate. * Note that successful completion of the query causes the ACPI_EC_SCI * bit to be cleared (and thus clearing the interrupt source).
*/
result = acpi_ec_transaction(ec, &q->transaction); if (result) goto err_exit;
if (!value) {
result = -ENODATA; goto err_exit;
}
q->handler = acpi_ec_get_query_handler_by_value(ec, value); if (!q->handler) {
result = -ENODATA; goto err_exit;
}
/* * It is reported that _Qxx are evaluated in a parallel way on Windows: * https://bugzilla.kernel.org/show_bug.cgi?id=94411 * * Put this log entry before queue_work() to make it appear in the log * before any other messages emitted during workqueue handling.
*/
ec_dbg_evt("Query(0x%02x) scheduled", value);
while (ec->events_to_process) {
spin_unlock_irq(&ec->lock);
acpi_ec_submit_query(ec);
spin_lock_irq(&ec->lock);
ec->events_to_process--;
}
/* * Before exit, make sure that the it will be possible to queue up the * event handling work again regardless of whether or not the query * queued up above is processed successfully.
*/ if (ec_event_clearing == ACPI_EC_EVT_TIMING_EVENT) { bool guard_timeout;
acpi_ec_complete_event(ec);
ec_dbg_evt("Event stopped");
spin_unlock_irq(&ec->lock);
guard_timeout = !!ec_guard(ec);
spin_lock_irq(&ec->lock);
/* Take care of SCI_EVT unless someone else is doing that. */ if (guard_timeout && !ec->curr)
advance_transaction(ec, false);
} else {
acpi_ec_close_event(ec);
ec_dbg_evt("Event stopped");
}
ec->events_in_progress--;
spin_unlock_irq(&ec->lock);
}
staticvoid clear_gpe_and_advance_transaction(struct acpi_ec *ec, bool interrupt)
{ /* * Clear GPE_STS upfront to allow subsequent hardware GPE_STS 0->1 * changes to always trigger a GPE interrupt. * * GPE STS is a W1C register, which means: * * 1. Software can clear it without worrying about clearing the other * GPEs' STS bits when the hardware sets them in parallel. * * 2. As long as software can ensure only clearing it when it is set, * hardware won't set it in parallel.
*/ if (ec->gpe >= 0 && acpi_ec_gpe_status_set(ec))
acpi_clear_gpe(NULL, ec->gpe);
/* clear addr values, ec_parse_io_ports depend on it */
ec->command_addr = ec->data_addr = 0;
status = acpi_walk_resources(handle, METHOD_NAME__CRS,
ec_parse_io_ports, ec); if (ACPI_FAILURE(status)) return status; if (ec->data_addr == 0 || ec->command_addr == 0) return AE_OK;
/* Get GPE bit assignment (EC events). */ /* TODO: Add support for _GPE returning a package */
status = acpi_evaluate_integer(handle, "_GPE", NULL, &tmp); if (ACPI_SUCCESS(status))
ec->gpe = tmp; /* * Errors are non-fatal, allowing for ACPI Reduced Hardware * platforms which use GpioInt instead of GPE.
*/
/* Use the global lock for all EC transactions? */
tmp = 0;
acpi_evaluate_integer(handle, "_GLK", NULL, &tmp);
ec->global_lock = tmp;
ec->handle = handle; return AE_CTRL_TERMINATE;
}
/** * ec_install_handlers - Install service callbacks and register query methods. * @ec: Target EC. * @device: ACPI device object corresponding to @ec. * @call_reg: If _REG should be called to notify OpRegion availability * * Install a handler for the EC address space type unless it has been installed * already. If @device is not NULL, also look for EC query methods in the * namespace and register them, and install an event (either GPE or GPIO IRQ) * handler for the EC, if possible. * * Return: * -ENODEV if the address space handler cannot be installed, which means * "unable to handle transactions", * -EPROBE_DEFER if GPIO IRQ acquisition needs to be deferred, * or 0 (success) otherwise.
*/ staticint ec_install_handlers(struct acpi_ec *ec, struct acpi_device *device, bool call_reg)
{
acpi_status status;
if (ec->gpe < 0) { /* ACPI reduced hardware platforms use a GpioInt from _CRS. */ int irq = acpi_dev_gpio_irq_get(device, 0); /* * Bail out right away for deferred probing or complete the * initialization regardless of any other errors.
*/ if (irq == -EPROBE_DEFER) return -EPROBE_DEFER; elseif (irq >= 0)
ec->irq = irq;
}
if (!test_bit(EC_FLAGS_QUERY_METHODS_INSTALLED, &ec->flags)) { /* Find and register all query methods */
acpi_walk_namespace(ACPI_TYPE_METHOD, ec->handle, 1,
acpi_ec_register_query_methods,
NULL, ec, NULL);
set_bit(EC_FLAGS_QUERY_METHODS_INSTALLED, &ec->flags);
} if (!test_bit(EC_FLAGS_EVENT_HANDLER_INSTALLED, &ec->flags)) { bool ready = false;
if (ready) {
set_bit(EC_FLAGS_EVENT_HANDLER_INSTALLED, &ec->flags);
acpi_ec_leave_noirq(ec);
} /* * Failures to install an event handler are not fatal, because * the EC can be polled for events.
*/
} /* EC is fully operational, allow queries */
acpi_ec_enable_event(ec);
if (test_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags)) { if (ACPI_FAILURE(acpi_remove_address_space_handler(
scope_handle,
ACPI_ADR_SPACE_EC,
&acpi_ec_space_handler)))
pr_err("failed to remove space handler\n");
clear_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags);
}
/* * Stops handling the EC transactions after removing the operation * region handler. This is required because _REG(DISCONNECT) * invoked during the removal can result in new EC transactions. * * Flushes the EC requests and thus disables the GPE before * removing the GPE handler. This is required by the current ACPICA * GPE core. ACPICA GPE core will automatically disable a GPE when * it is indicated but there is no way to handle it. So the drivers * must disable the GPEs prior to removing the GPE handlers.
*/
acpi_ec_stop(ec, false);
if (test_bit(EC_FLAGS_EVENT_HANDLER_INSTALLED, &ec->flags)) { if (ec->gpe >= 0 &&
ACPI_FAILURE(acpi_remove_gpe_handler(NULL, ec->gpe,
&acpi_ec_gpe_handler)))
pr_err("failed to remove gpe handler\n");
if (boot_ec && (boot_ec->handle == device->handle ||
!strcmp(acpi_device_hid(device), ACPI_ECDT_HID))) { /* Fast path: this device corresponds to the boot EC. */
ec = boot_ec;
} else {
acpi_status status;
ec = acpi_ec_alloc(); if (!ec) return -ENOMEM;
status = ec_parse_device(device->handle, 0, ec, NULL); if (status != AE_CTRL_TERMINATE) {
ret = -EINVAL; goto err;
}
if (boot_ec && ec->command_addr == boot_ec->command_addr &&
ec->data_addr == boot_ec->data_addr) { /* * Trust PNP0C09 namespace location rather than ECDT ID. * But trust ECDT GPE rather than _GPE because of ASUS * quirks. So do not change boot_ec->gpe to ec->gpe, * except when the TRUST_DSDT_GPE quirk is set.
*/
boot_ec->handle = ec->handle;
if (EC_FLAGS_TRUST_DSDT_GPE)
boot_ec->gpe = ec->gpe;
acpi_handle_info(ec->handle, "EC: Used to handle transactions and events\n");
device->driver_data = ec;
ret = !!request_region(ec->data_addr, 1, "EC data");
WARN(!ret, "Could not request EC data io port 0x%lx", ec->data_addr);
ret = !!request_region(ec->command_addr, 1, "EC cmd");
WARN(!ret, "Could not request EC cmd io port 0x%lx", ec->command_addr);
/* Reprobe devices depending on the EC */
acpi_dev_clear_dependencies(device);
if (resource->type != ACPI_RESOURCE_TYPE_IO) return AE_OK;
/* * The first address region returned is the data port, and * the second address region returned is the status/command * port.
*/ if (ec->data_addr == 0)
ec->data_addr = resource->data.io.minimum; elseif (ec->command_addr == 0)
ec->command_addr = resource->data.io.minimum; else return AE_CTRL_TERMINATE;
/* * This function is not Windows-compatible as Windows never enumerates the * namespace EC before the main ACPI device enumeration process. It is * retained for historical reason and will be deprecated in the future.
*/ void __init acpi_ec_dsdt_probe(void)
{ struct acpi_ec *ec;
acpi_status status; int ret;
/* * If a platform has ECDT, there is no need to proceed as the * following probe is not a part of the ACPI device enumeration, * executing _STA is not safe, and thus this probe may risk of * picking up an invalid EC device.
*/ if (boot_ec) return;
ec = acpi_ec_alloc(); if (!ec) return;
/* * At this point, the namespace is initialized, so start to find * the namespace objects.
*/
status = acpi_get_devices(ec_device_ids[0].id, ec_parse_device, ec, NULL); if (ACPI_FAILURE(status) || !ec->handle) {
acpi_ec_free(ec); return;
}
/* * When the DSDT EC is available, always re-configure boot EC to * have _REG evaluated. _REG can only be evaluated after the * namespace initialization. * At this point, the GPE is not fully initialized, so do not to * handle the events.
*/
ret = acpi_ec_setup(ec, NULL, true); if (ret) {
acpi_ec_free(ec); return;
}
boot_ec = ec;
acpi_handle_info(ec->handle, "Boot DSDT EC used to handle transactions\n");
}
/* * acpi_ec_ecdt_start - Finalize the boot ECDT EC initialization. * * First, look for an ACPI handle for the boot ECDT EC if acpi_ec_add() has not * found a matching object in the namespace. * * Next, in case the DSDT EC is not functioning, it is still necessary to * provide a functional ECDT EC to handle events, so add an extra device object * to represent it (see https://bugzilla.kernel.org/show_bug.cgi?id=115021). * * This is useful on platforms with valid ECDT and invalid DSDT EC settings, * like ASUS X550ZE (see https://bugzilla.kernel.org/show_bug.cgi?id=196847).
*/ staticvoid __init acpi_ec_ecdt_start(void)
{ struct acpi_table_ecdt *ecdt_ptr;
acpi_handle handle;
acpi_status status;
/* Bail out if a matching EC has been found in the namespace. */ if (!boot_ec || boot_ec->handle != ACPI_ROOT_OBJECT) return;
/* Look up the object pointed to from the ECDT in the namespace. */
status = acpi_get_table(ACPI_SIG_ECDT, 1,
(struct acpi_table_header **)&ecdt_ptr); if (ACPI_FAILURE(status)) return;
status = acpi_get_handle(NULL, ecdt_ptr->id, &handle); if (ACPI_SUCCESS(status)) {
boot_ec->handle = handle;
/* Add a special ACPI device object to represent the boot EC. */
acpi_bus_register_early_device(ACPI_BUS_TYPE_ECDT_EC);
}
/* * On some hardware it is necessary to clear events accumulated by the EC during * sleep. These ECs stop reporting GPEs until they are manually polled, if too * many events are accumulated. (e.g. Samsung Series 5/9 notebooks) * * https://bugzilla.kernel.org/show_bug.cgi?id=44161 * * Ideally, the EC should also be instructed NOT to accumulate events during * sleep (which Windows seems to do somehow), but the interface to control this * behaviour is not known at this time. * * Models known to be affected are Samsung 530Uxx/535Uxx/540Uxx/550Pxx/900Xxx, * however it is very likely that other Samsung models are affected. * * On systems which don't accumulate _Q events during sleep, this extra check * should be harmless.
*/ staticint ec_clear_on_resume(conststruct dmi_system_id *id)
{
pr_debug("Detected system needing EC poll on resume.\n");
EC_FLAGS_CLEAR_ON_RESUME = 1;
ec_event_clearing = ACPI_EC_EVT_TIMING_STATUS; return 0;
}
/* * Some ECDTs contain wrong GPE setting, but they share the same port addresses * with DSDT EC, don't duplicate the DSDT EC with ECDT EC in this case. * https://bugzilla.kernel.org/show_bug.cgi?id=209989
*/ staticint ec_honor_dsdt_gpe(conststruct dmi_system_id *id)
{
pr_debug("Detected system needing DSDT GPE setting.\n");
EC_FLAGS_TRUST_DSDT_GPE = 1; return 0;
}
if (!strlen(ecdt_ptr->id)) { /* * The ECDT table on some MSI notebooks contains invalid data, together * with an empty ID string (""). * * Section 5.2.15 of the ACPI specification requires the ID string to be * a "fully qualified reference to the (...) embedded controller device", * so this string always has to start with a backslash. * * However some ThinkBook machines have a ECDT table with a valid EC * description but an invalid ID string ("_SB.PC00.LPCB.EC0"). * * Because of this we only check if the ID string is empty in order to * avoid the obvious cases.
*/
pr_err(FW_BUG "Ignoring ECDT due to empty ID string\n"); goto out;
}
/* * Ignore the GPE value on Reduced Hardware platforms. * Some products have this set to an erroneous value.
*/ if (!acpi_gbl_reduced_hardware)
ec->gpe = ecdt_ptr->gpe;
ec->handle = ACPI_ROOT_OBJECT;
/* * At this point, the namespace is not initialized, so do not find * the namespace objects, or handle the events.
*/
ret = acpi_ec_setup(ec, NULL, false); if (ret) {
acpi_ec_free(ec); goto out;
}
boot_ec = ec;
boot_ec_is_ecdt = true;
pr_info("Boot ECDT EC used to handle transactions\n");
/* * The SCI handler doesn't run at this point, so the GPE can be * masked at the low level without side effects.
*/ if (ec_no_wakeup && test_bit(EC_FLAGS_STARTED, &ec->flags) &&
ec->gpe >= 0 && ec->reference_count >= 1)
acpi_set_gpe(NULL, ec->gpe, ACPI_GPE_DISABLE);
if (!first_ec) return acpi_any_gpe_status_set(U32_MAX);
/* * Report wakeup if the status bit is set for any enabled GPE other * than the EC one.
*/ if (acpi_any_gpe_status_set(first_ec->gpe)) returntrue;
/* * Cancel the SCI wakeup and process all pending events in case there * are any wakeup ones in there. * * Note that if any non-EC GPEs are active at this point, the SCI will * retrigger after the rearming in acpi_s2idle_wake(), so no events * should be missed by canceling the wakeup here.
*/
pm_system_cancel_wakeup();
/* * Dispatch the EC GPE in-band, but do not report wakeup in any case * to allow the caller to process events properly after that.
*/
spin_lock_irq(&first_ec->lock);
if (acpi_ec_gpe_status_set(first_ec)) {
pm_pr_dbg("ACPI EC GPE status set\n");
result = acpi_ec_init_workqueues(); if (result) return;
/* * Disable EC wakeup on following systems to prevent periodic * wakeup from EC GPE.
*/ if (dmi_check_system(acpi_ec_no_wakeup)) {
ec_no_wakeup = true;
pr_debug("Disabling EC wakeup on suspend-to-idle\n");
}
/* Driver must be registered after acpi_ec_init_workqueues(). */
acpi_bus_register_driver(&acpi_ec_driver);
acpi_ec_ecdt_start();
}
/* EC driver currently not unloadable */ #if 0 staticvoid __exit acpi_ec_exit(void)
{
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.