2009-07-29 04:45:54 +08:00
|
|
|
/*
|
|
|
|
* acpi/internal.h
|
|
|
|
* For use by Linux/ACPI infrastructure, not drivers
|
|
|
|
*
|
|
|
|
* Copyright (c) 2009, Intel Corporation.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
|
|
* under the terms and conditions of the GNU General Public License,
|
|
|
|
* version 2, as published by the Free Software Foundation.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
|
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
|
|
* more details.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2010-07-16 19:11:31 +08:00
|
|
|
#ifndef _ACPI_INTERNAL_H_
|
|
|
|
#define _ACPI_INTERNAL_H_
|
|
|
|
|
2009-07-29 04:45:54 +08:00
|
|
|
#define PREFIX "ACPI: "
|
2009-03-14 02:08:26 +08:00
|
|
|
|
2016-05-03 16:49:01 +08:00
|
|
|
int early_acpi_osi_init(void);
|
|
|
|
int acpi_osi_init(void);
|
2013-07-23 16:11:55 +08:00
|
|
|
acpi_status acpi_os_initialize1(void);
|
2015-09-11 04:48:09 +08:00
|
|
|
void init_acpi_device_notify(void);
|
2009-03-25 06:49:43 +08:00
|
|
|
int acpi_scan_init(void);
|
2013-01-30 21:27:33 +08:00
|
|
|
void acpi_pci_root_init(void);
|
2013-01-30 21:27:37 +08:00
|
|
|
void acpi_pci_link_init(void);
|
ACPI / processor: Use common hotplug infrastructure
Split the ACPI processor driver into two parts, one that is
non-modular, resides in the ACPI core and handles the enumeration
and hotplug of processors and one that implements the rest of the
existing processor driver functionality.
The non-modular part uses an ACPI scan handler object to enumerate
processors on the basis of information provided by the ACPI namespace
and to hook up with the common ACPI hotplug infrastructure. It also
populates the ACPI handle of each processor device having a
corresponding object in the ACPI namespace, which allows the driver
proper to bind to those devices, and makes the driver bind to them
if it is readily available (i.e. loaded) when the scan handler's
.attach() routine is running.
There are a few reasons to make this change.
First, switching the ACPI processor driver to using the common ACPI
hotplug infrastructure reduces code duplication and size considerably,
even though a new file is created along with a header comment etc.
Second, since the common hotplug code attempts to offline devices
before starting the (non-reversible) removal procedure, it will abort
(and possibly roll back) hot-remove operations involving processors
if cpu_down() returns an error code for one of them instead of
continuing them blindly (if /sys/firmware/acpi/hotplug/force_remove
is unset). That is a more desirable behavior than what the current
code does.
Finally, the separation of the scan/hotplug part from the driver
proper makes it possible to simplify the driver's .remove() routine,
because it doesn't need to worry about the possible cleanup related
to processor removal any more (the scan/hotplug part is responsible
for that now) and can handle device removal and driver removal
symmetricaly (i.e. as appropriate).
Some user-visible changes in sysfs are made (for example, the
'sysdev' link from the ACPI device node to the processor device's
directory is gone and a 'physical_node' link is present instead
and a corresponding 'firmware_node' is present in the processor
device's directory, the processor driver is now visible under
/sys/bus/cpu/drivers/ and bound to the processor device), but
that shouldn't affect the functionality that users care about
(frequency scaling, C-states and thermal management).
Tested on my venerable Toshiba Portege R500.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Reviewed-by: Toshi Kani <toshi.kani@hp.com>
2013-05-03 06:26:22 +08:00
|
|
|
void acpi_processor_init(void);
|
2013-01-30 21:27:40 +08:00
|
|
|
void acpi_platform_init(void);
|
ACPI / PNP: use device ID list for PNPACPI device enumeration
ACPI can be used to enumerate PNP devices, but the code does not
handle this in the right way currently. Namely, if an ACPI device
object
1. Has a _CRS method,
2. Has an identification of
"three capital characters followed by four hex digits",
3. Is not in the excluded IDs list,
it will be enumerated to PNP bus (that is, a PNP device object will
be create for it). This means that, actually, the PNP bus type is
used as the default bus type for enumerating _HID devices in ACPI.
However, more and more _HID devices need to be enumerated to the
platform bus instead (that is, platform device objects need to be
created for them). As a result, the device ID list in acpi_platform.c
is used to enforce creating platform device objects rather than PNP
device objects for matching devices. That list has been continuously
growing recently, unfortunately, and it is pretty much guaranteed to
grow even more in the future.
To address that problem it is better to enumerate _HID devices
as platform devices by default. To this end, change the way of
enumerating PNP devices by adding a PNP ACPI scan handler that
will use a device ID list to create PNP devices for the ACPI
device objects whose device IDs are present in that list.
The initial device ID list in the PNP ACPI scan handler contains
all of the pnp_device_id strings from all the existing PNP drivers,
so this change should be transparent to the PNP core and all of the
PNP drivers. Still, in the future it should be possible to reduce
its size by converting PNP drivers that need not be PNP for any
technical reasons into platform drivers.
Signed-off-by: Zhang Rui <rui.zhang@intel.com>
[rjw: Rewrote the changelog, modified the PNP ACPI scan handler code]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
2014-05-30 10:23:01 +08:00
|
|
|
void acpi_pnp_init(void);
|
2014-03-14 00:34:05 +08:00
|
|
|
void acpi_int340x_thermal_init(void);
|
2016-01-20 22:29:27 +08:00
|
|
|
#ifdef CONFIG_ARM_AMBA
|
|
|
|
void acpi_amba_init(void);
|
|
|
|
#else
|
|
|
|
static inline void acpi_amba_init(void) {}
|
|
|
|
#endif
|
2010-07-15 10:46:30 +08:00
|
|
|
int acpi_sysfs_init(void);
|
2016-12-16 12:07:57 +08:00
|
|
|
void acpi_gpe_apply_masked_gpes(void);
|
2013-02-09 06:52:39 +08:00
|
|
|
void acpi_container_init(void);
|
2014-05-30 10:29:14 +08:00
|
|
|
void acpi_memory_hotplug_init(void);
|
2015-02-05 13:44:49 +08:00
|
|
|
#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC
|
2017-02-28 21:34:29 +08:00
|
|
|
void pci_ioapic_remove(struct acpi_pci_root *root);
|
2015-02-05 13:44:49 +08:00
|
|
|
int acpi_ioapic_remove(struct acpi_pci_root *root);
|
|
|
|
#else
|
2017-02-28 21:34:29 +08:00
|
|
|
static inline void pci_ioapic_remove(struct acpi_pci_root *root) { return; }
|
2015-02-05 13:44:49 +08:00
|
|
|
static inline int acpi_ioapic_remove(struct acpi_pci_root *root) { return 0; }
|
|
|
|
#endif
|
2013-06-23 06:59:55 +08:00
|
|
|
#ifdef CONFIG_ACPI_DOCK
|
ACPI / dock: Dispatch dock notifications from the global notify handler
The ACPI dock station code carries out an extra namespace scan
before the main one in order to find and register all of the dock
device objects. Then, it registers a notify handler for each of
them for handling dock events.
However, dock device objects need not be scanned for upfront. They
very well can be enumerated and registered during the first phase
of the main namespace scan, before attaching scan handlers and ACPI
drivers to ACPI device objects. Then, the dependent devices can be
added to the in the second phase. That makes it possible to drop
the extra namespace scan, so do it.
Moreover, it is not necessary to register notify handlers for all
of the dock stations' namespace nodes, becuase notifications may
be dispatched from the global notify handler for them. Do that and
drop two functions used for dock notify handling, acpi_dock_deferred_cb()
and dock_notify_handler(), that aren't necessary any more.
Finally, some dock station objects have _HID objects matching the
ACPI container scan handler which causes it to claim those objects
and try to handle their hotplug, but that is not a good idea,
because those objects have their own special hotplug handling anyway.
For this reason, the hotplug_notify flag should not be set for ACPI
device objects representing dock stations and the container scan
handler should be made ignore those objects, so make that happen.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2014-02-16 08:51:01 +08:00
|
|
|
void register_dock_dependent_device(struct acpi_device *adev,
|
|
|
|
acpi_handle dshandle);
|
|
|
|
int dock_notify(struct acpi_device *adev, u32 event);
|
|
|
|
void acpi_dock_add(struct acpi_device *adev);
|
2013-06-23 06:59:55 +08:00
|
|
|
#else
|
ACPI / dock: Dispatch dock notifications from the global notify handler
The ACPI dock station code carries out an extra namespace scan
before the main one in order to find and register all of the dock
device objects. Then, it registers a notify handler for each of
them for handling dock events.
However, dock device objects need not be scanned for upfront. They
very well can be enumerated and registered during the first phase
of the main namespace scan, before attaching scan handlers and ACPI
drivers to ACPI device objects. Then, the dependent devices can be
added to the in the second phase. That makes it possible to drop
the extra namespace scan, so do it.
Moreover, it is not necessary to register notify handlers for all
of the dock stations' namespace nodes, becuase notifications may
be dispatched from the global notify handler for them. Do that and
drop two functions used for dock notify handling, acpi_dock_deferred_cb()
and dock_notify_handler(), that aren't necessary any more.
Finally, some dock station objects have _HID objects matching the
ACPI container scan handler which causes it to claim those objects
and try to handle their hotplug, but that is not a good idea,
because those objects have their own special hotplug handling anyway.
For this reason, the hotplug_notify flag should not be set for ACPI
device objects representing dock stations and the container scan
handler should be made ignore those objects, so make that happen.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2014-02-16 08:51:01 +08:00
|
|
|
static inline void register_dock_dependent_device(struct acpi_device *adev,
|
|
|
|
acpi_handle dshandle) {}
|
|
|
|
static inline int dock_notify(struct acpi_device *adev, u32 event) { return -ENODEV; }
|
|
|
|
static inline void acpi_dock_add(struct acpi_device *adev) {}
|
2013-06-23 06:59:55 +08:00
|
|
|
#endif
|
2013-06-05 10:27:50 +08:00
|
|
|
#ifdef CONFIG_X86
|
|
|
|
void acpi_cmos_rtc_init(void);
|
|
|
|
#else
|
|
|
|
static inline void acpi_cmos_rtc_init(void) {}
|
|
|
|
#endif
|
2015-07-03 07:06:00 +08:00
|
|
|
int acpi_rev_override_setup(char *str);
|
2009-03-25 06:49:43 +08:00
|
|
|
|
2013-03-04 06:08:16 +08:00
|
|
|
void acpi_sysfs_add_hotplug_profile(struct acpi_hotplug_profile *hotplug,
|
|
|
|
const char *name);
|
|
|
|
int acpi_scan_add_handler_with_hotplug(struct acpi_scan_handler *handler,
|
|
|
|
const char *hotplug_profile_name);
|
|
|
|
void acpi_scan_hotplug_enabled(struct acpi_hotplug_profile *hotplug, bool val);
|
|
|
|
|
2010-07-15 10:46:15 +08:00
|
|
|
#ifdef CONFIG_DEBUG_FS
|
2011-05-26 18:26:23 +08:00
|
|
|
extern struct dentry *acpi_debugfs_dir;
|
2015-08-01 21:32:17 +08:00
|
|
|
void acpi_debugfs_init(void);
|
2010-07-15 10:46:15 +08:00
|
|
|
#else
|
2011-05-26 18:26:23 +08:00
|
|
|
static inline void acpi_debugfs_init(void) { return; }
|
2010-07-15 10:46:15 +08:00
|
|
|
#endif
|
2013-03-07 06:46:20 +08:00
|
|
|
void acpi_lpss_init(void);
|
2010-07-15 10:46:15 +08:00
|
|
|
|
2015-02-06 08:27:51 +08:00
|
|
|
void acpi_apd_init(void);
|
|
|
|
|
2014-03-03 07:40:38 +08:00
|
|
|
acpi_status acpi_hotplug_schedule(struct acpi_device *adev, u32 src);
|
2013-11-23 04:52:12 +08:00
|
|
|
bool acpi_queue_hotplug_work(struct work_struct *work);
|
2014-03-03 07:40:38 +08:00
|
|
|
void acpi_device_hotplug(struct acpi_device *adev, u32 src);
|
ACPI / hotplug / driver core: Handle containers in a special way
ACPI container devices require special hotplug handling, at least
on some systems, since generally user space needs to carry out
system-specific cleanup before it makes sense to offline devices in
the container. However, the current ACPI hotplug code for containers
first attempts to offline devices in the container and only then it
notifies user space of the container offline.
Moreover, after commit 202317a573b2 (ACPI / scan: Add acpi_device
objects for all device nodes in the namespace), ACPI device objects
representing containers are present as long as the ACPI namespace
nodes corresponding to them are present, which may be forever, even
if the container devices are physically detached from the system (the
return values of the corresponding _STA methods change in those
cases, but generally the namespace nodes themselves are still there).
Thus it is useful to introduce entities representing containers that
will go away during container hot-unplug.
The goal of this change is to address both the above issues.
The idea is to create a "companion" container system device for each
of the ACPI container device objects during the initial namespace
scan or on a hotplug event making the container present. That system
device will be unregistered on container removal. A new bus type
for container devices is added for this purpose, because device
offline and online operations need to be defined for them. The
online operation is a trivial function that is always successful
and the offline uses a callback pointed to by the container device's
offline member.
For ACPI containers that callback simply walks the list of ACPI
device objects right below the container object (its children) and
checks if all of their physical companion devices are offline. If
that's not the case, it returns -EBUSY and the container system
devivce cannot be put offline. Consequently, to put the container
system device offline, it is necessary to put all of the physical
devices depending on its ACPI companion object offline beforehand.
Container system devices created for ACPI container objects are
initially online. They are created by the container ACPI scan
handler whose hotplug.demand_offline flag is set. That causes
acpi_scan_hot_remove() to check if the companion container system
device is offline before attempting to remove an ACPI container or
any devices below it. If the check fails, a KOBJ_CHANGE uevent is
emitted for the container system device in question and user space
is expected to offline all devices below the container and the
container itself in response to it. Then, user space can finalize
the removal of the container with the help of its ACPI device
object's eject attribute in sysfs.
Tested-by: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-12-29 22:25:48 +08:00
|
|
|
bool acpi_scan_is_offline(struct acpi_device *adev, bool uevent);
|
2013-11-23 04:52:12 +08:00
|
|
|
|
2016-07-09 00:13:09 +08:00
|
|
|
acpi_status acpi_sysfs_table_handler(u32 event, void *table, void *context);
|
|
|
|
void acpi_scan_table_handler(u32 event, void *table, void *context);
|
|
|
|
|
2013-01-17 21:11:05 +08:00
|
|
|
/* --------------------------------------------------------------------------
|
|
|
|
Device Node Initialization / Removal
|
|
|
|
-------------------------------------------------------------------------- */
|
|
|
|
#define ACPI_STA_DEFAULT (ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED | \
|
|
|
|
ACPI_STA_DEVICE_UI | ACPI_STA_DEVICE_FUNCTIONING)
|
|
|
|
|
2015-11-26 04:19:55 +08:00
|
|
|
extern struct list_head acpi_bus_id_list;
|
|
|
|
|
2016-01-02 05:52:15 +08:00
|
|
|
struct acpi_device_bus_id {
|
2015-11-26 04:19:55 +08:00
|
|
|
char bus_id[15];
|
|
|
|
unsigned int instance_no;
|
|
|
|
struct list_head node;
|
|
|
|
};
|
|
|
|
|
2013-01-24 19:49:49 +08:00
|
|
|
int acpi_device_add(struct acpi_device *device,
|
|
|
|
void (*release)(struct device *));
|
2013-01-17 21:11:05 +08:00
|
|
|
void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
|
|
|
|
int type, unsigned long long sta);
|
2015-07-18 04:53:43 +08:00
|
|
|
int acpi_device_setup_files(struct acpi_device *dev);
|
|
|
|
void acpi_device_remove_files(struct acpi_device *dev);
|
2013-01-24 19:49:49 +08:00
|
|
|
void acpi_device_add_finalize(struct acpi_device *device);
|
2013-03-05 05:30:42 +08:00
|
|
|
void acpi_free_pnp_ids(struct acpi_device_pnp *pnp);
|
2017-06-06 17:37:36 +08:00
|
|
|
bool acpi_device_is_present(const struct acpi_device *adev);
|
2014-02-16 07:09:34 +08:00
|
|
|
bool acpi_device_is_battery(struct acpi_device *adev);
|
2015-07-27 23:03:57 +08:00
|
|
|
bool acpi_device_is_first_physical_node(struct acpi_device *adev,
|
|
|
|
const struct device *dev);
|
2013-01-17 21:11:05 +08:00
|
|
|
|
2015-07-18 04:53:43 +08:00
|
|
|
/* --------------------------------------------------------------------------
|
|
|
|
Device Matching and Notification
|
|
|
|
-------------------------------------------------------------------------- */
|
|
|
|
struct acpi_device *acpi_companion_match(const struct device *dev);
|
|
|
|
int __acpi_device_uevent_modalias(struct acpi_device *adev,
|
|
|
|
struct kobj_uevent_env *env);
|
|
|
|
|
2009-03-14 02:08:26 +08:00
|
|
|
/* --------------------------------------------------------------------------
|
|
|
|
Power Resource
|
|
|
|
-------------------------------------------------------------------------- */
|
2009-03-25 06:49:53 +08:00
|
|
|
int acpi_power_init(void);
|
2013-01-17 21:11:06 +08:00
|
|
|
void acpi_power_resources_list_free(struct list_head *list);
|
2013-01-17 21:11:07 +08:00
|
|
|
int acpi_extract_power_resources(union acpi_object *package, unsigned int start,
|
|
|
|
struct list_head *list);
|
|
|
|
int acpi_add_power_resource(acpi_handle handle);
|
ACPI / PM: Rework the handling of devices depending on power resources
Commit 0090def6 (ACPI: Add interface to register/unregister device
to/from power resources) made it possible to indicate to the ACPI
core that if the given device depends on any power resources, then
it should be resumed as soon as all of the power resources required
by it to transition to the D0 power state have been turned on.
Unfortunately, however, this was a mistake, because all devices
depending on power resources should be treated this way (i.e. they
should be resumed when all power resources required by their D0
state have been turned on) and for the majority of those devices
the ACPI core can figure out by itself which (physical) devices
depend on what power resources.
For this reason, replace the code added by commit 0090def6 with a
new, much more straightforward, mechanism that will be used
internally by the ACPI core and remove all references to that code
from kernel subsystems using ACPI.
For the cases when there are (physical) devices that should be
resumed whenever a not directly related ACPI device node goes into
D0 as a result of power resources configuration changes, like in
the SATA case, add two new routines, acpi_dev_pm_add_dependent()
and acpi_dev_pm_remove_dependent(), allowing subsystems to manage
such dependencies. Convert the SATA subsystem to use the new
functions accordingly.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2013-01-17 21:11:05 +08:00
|
|
|
void acpi_power_add_remove_device(struct acpi_device *adev, bool add);
|
ACPI / PM: Take unusual configurations of power resources into account
Commit d2e5f0c (ACPI / PCI: Rework the setup and cleanup of device
wakeup) moved the initial disabling of system wakeup for PCI devices
into a place where it can actually work and that exposed a hidden old
issue with crap^Wunusual system designs where the same power
resources are used for both wakeup power and device power control at
run time.
Namely, say there is one power resource such that the ACPI power
state D0 of a PCI device depends on that power resource (i.e. the
device is in D0 when that power resource is "on") and it is used
as a wakeup power resource for the same device. Then, calling
acpi_pci_sleep_wake(pci_dev, false) for the device in question will
cause the reference counter of that power resource to drop to 0,
which in turn will cause it to be turned off. As a result, the
device will go into D3cold at that point, although it should have
stayed in D0.
As it turns out, that happens to USB controllers on some laptops
and USB becomes unusable on those machines as a result, which is
a major regression from v3.8.
To fix this problem, (1) increment the reference counters of wakup
power resources during their initialization if they are "on"
initially, (2) prevent acpi_disable_wakeup_device_power() from
decrementing the reference counters of wakeup power resources that
were not enabled for wakeup power previously, and (3) prevent
acpi_enable_wakeup_device_power() from incrementing the reference
counters of wakeup power resources that already are enabled for
wakeup power.
In addition to that, if it is impossible to determine the initial
states of wakeup power resources, avoid enabling wakeup for devices
whose wakeup power depends on those power resources.
Reported-by: Dave Jones <davej@redhat.com>
Reported-by: Fabio Baltieri <fabio.baltieri@linaro.org>
Tested-by: Fabio Baltieri <fabio.baltieri@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2013-02-24 06:15:21 +08:00
|
|
|
int acpi_power_wakeup_list_init(struct list_head *list, int *system_level);
|
2009-03-14 02:08:26 +08:00
|
|
|
int acpi_device_sleep_wake(struct acpi_device *dev,
|
|
|
|
int enable, int sleep_state, int dev_state);
|
2010-11-25 07:05:17 +08:00
|
|
|
int acpi_power_get_inferred_state(struct acpi_device *device, int *state);
|
2010-11-25 07:06:55 +08:00
|
|
|
int acpi_power_on_resources(struct acpi_device *device, int state);
|
2009-03-14 02:08:26 +08:00
|
|
|
int acpi_power_transition(struct acpi_device *device, int state);
|
|
|
|
|
2009-03-25 06:50:19 +08:00
|
|
|
int acpi_wakeup_device_init(void);
|
2014-07-18 18:02:54 +08:00
|
|
|
|
|
|
|
#ifdef CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC
|
2009-12-21 03:19:09 +08:00
|
|
|
void acpi_early_processor_set_pdc(void);
|
2014-07-18 18:02:54 +08:00
|
|
|
#else
|
|
|
|
static inline void acpi_early_processor_set_pdc(void) {}
|
|
|
|
#endif
|
2009-03-25 06:50:19 +08:00
|
|
|
|
2016-03-24 12:07:39 +08:00
|
|
|
#ifdef CONFIG_X86
|
|
|
|
void acpi_early_processor_osc(void);
|
|
|
|
#else
|
|
|
|
static inline void acpi_early_processor_osc(void) {}
|
|
|
|
#endif
|
|
|
|
|
2009-03-14 02:08:26 +08:00
|
|
|
/* --------------------------------------------------------------------------
|
|
|
|
Embedded Controller
|
|
|
|
-------------------------------------------------------------------------- */
|
2010-07-16 19:11:31 +08:00
|
|
|
struct acpi_ec {
|
|
|
|
acpi_handle handle;
|
|
|
|
unsigned long gpe;
|
|
|
|
unsigned long command_addr;
|
|
|
|
unsigned long data_addr;
|
2015-09-27 06:04:07 +08:00
|
|
|
bool global_lock;
|
2010-07-16 19:11:31 +08:00
|
|
|
unsigned long flags;
|
2015-02-06 08:57:59 +08:00
|
|
|
unsigned long reference_count;
|
2012-10-23 07:29:27 +08:00
|
|
|
struct mutex mutex;
|
2010-07-16 19:11:31 +08:00
|
|
|
wait_queue_head_t wait;
|
|
|
|
struct list_head list;
|
|
|
|
struct transaction *curr;
|
2012-10-23 07:29:27 +08:00
|
|
|
spinlock_t lock;
|
ACPI / EC: Fix issues related to the SCI_EVT handling
This patch fixes 2 issues related to the draining behavior. But it doesn't
implement the draining support, it only cleans up code so that further
draining support is possible.
The draining behavior is expected by some platforms (for example, Samsung)
where SCI_EVT is set only once for a set of events and might be cleared for
the very first QR_EC command issued after SCI_EVT is set. EC firmware on
such platforms will return 0x00 to indicate "no outstanding event". Thus
after seeing an SCI_EVT indication, EC driver need to fetch events until
0x00 returned (see acpi_ec_clear()).
Issue 1 - acpi_ec_submit_query():
It's reported on Samsung laptops that SCI_EVT isn't checked when the
transactions are advanced in ec_poll(), which leads to SCI_EVT triggering
source lost:
If no EC GPE IRQs are arrived after that, EC driver cannot detect this
event and handle it.
See comment 244/247 for kernel bugzilla 44161.
This patch fixes this issue by moving SCI_EVT checks into
advance_transaction(). So that SCI_EVT is checked each time we are going to
handle the EC firmware indications. And this check will happen for both IRQ
context and task context.
Since after doing that, SCI_EVT is also checked after completing a
transaction, ec_check_sci() and ec_check_sci_sync() can be removed.
Issue 2 - acpi_ec_complete_query():
We expect to clear EC_FLAGS_QUERY_PENDING to allow queuing another draining
QR_EC after writing a QR_EC command and before reading the event. After
reading the event, SCI_EVT might be cleared by the firmware, thus it may
not be possible to queue such a draining QR_EC at that time.
But putting the EC_FLAGS_QUERY_PENDING clearing code after
start_transaction() is wrong as there are chances that after
start_transaction(), QR_EC can fail to be sent. If this happens,
EC_FLAG_QUERY_PENDING will be cleared earlier. As a consequence, the
draining QR_EC will also be queued earlier than expected.
This patch also moves this code into advance_transaction() where QR_EC is
just sent (ACPI_EC_COMMAND_POLL flagged) to fix this issue.
Notes:
1. After introducing the 2 SCI_EVT related handlings into
advance_transaction(), a next QR_EC can be queued right after writing
the current QR_EC command and before reading the event. But this still
hasn't implemented the draining behavior as the draining support
requires:
If a previous returned event value isn't 0x00, a draining QR_EC need
to be issued even when SCI_EVT isn't set.
2. In this patch, acpi_os_execute() is also converted into a seperate work
item to avoid invoking kmalloc() in the atomic context. We can do this
because of the previous global lock fix.
3. Originally, EC_FLAGS_EVENT_PENDING is also used to avoid queuing up
multiple work items (created by acpi_os_execute()), this can be covered
by only using a single work item. But this patch still keeps this flag
as there are different usages in the driver initialization steps relying
on this flag.
Link: https://bugzilla.kernel.org/show_bug.cgi?id=44161
Reported-by: Kieran Clancy <clancy.kieran@gmail.com>
Signed-off-by: Lv Zheng <lv.zheng@intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2015-01-14 19:28:47 +08:00
|
|
|
struct work_struct work;
|
ACPI / EC: Fix and clean up register access guarding logics.
In the polling mode, EC driver shouldn't access the EC registers too
frequently. Though this statement is concluded from the non-root caused
bugs (see links below), we've maintained the register access guarding
logics in the current EC driver. The guarding logics can be found here and
there, makes it hard to root cause real timing issues. This patch collects
the guarding logics into one single function so that all hidden logics
related to this can be seen clearly.
The current guarding related code also has several issues:
1. Per-transaction timestamp prevents inter-transaction guarding from being
implemented in the same place. We have an inter-transaction udelay() in
acpi_ec_transaction_unblocked(), this logic can be merged into ec_poll()
if we can use per-device timestamp. This patch completes such merge to
form a new ec_guard() function and collects all guarding related hidden
logics in it.
One hidden logic is: there is no inter-transaction guarding performed
for non MSI quirk (wait polling mode), this patch skips
inter-transaction guarding before wait_event_timeout() for the wait
polling mode to reveal the hidden logic.
The other hidden logic is: there is msleep() inter-transaction guarding
performed when the GPE storming is observed. As after merging this
commit:
Commit: e1d4d90fc0313d3d58cbd7912c90f8ef24df45ff
Subject: ACPI / EC: Refine command storm prevention support
EC_FLAGS_COMMAND_STORM is ensured to be cleared after invoking
acpi_ec_transaction_unlocked(), the msleep() guard logic will never
happen now. Since no one complains such change, this logic is likely
added during the old times where the EC race issues are not fixed and
the bugs are false root-caused to the timing issue. This patch simply
removes the out-dated logic. We can restore it by stop skipping
inter-transaction guarding for wait polling mode.
Two different delay values are defined for msleep() and udelay() while
they are merged in this patch to 550us.
2. time_after() causes additional delay in the polling mode (can only be
observed in noirq suspend/resume processes where polling mode is always
used) before advance_transaction() is invoked ("wait polling" log is
added before wait_event_timeout()). We can see 2 wait_event_timeout()
invocations. This is because time_after() ensures a ">" validation while
we only need a ">=" validation here:
[ 86.739909] ACPI: Waking up from system sleep state S3
[ 86.742857] ACPI : EC: 2: Increase command
[ 86.742859] ACPI : EC: ***** Command(RD_EC) started *****
[ 86.742861] ACPI : EC: ===== TASK (0) =====
[ 86.742871] ACPI : EC: EC_SC(R) = 0x20 SCI_EVT=1 BURST=0 CMD=0 IBF=0 OBF=0
[ 86.742873] ACPI : EC: EC_SC(W) = 0x80
[ 86.742876] ACPI : EC: ***** Event started *****
[ 86.742880] ACPI : EC: ~~~~~ wait polling ~~~~~
[ 86.743972] ACPI : EC: ~~~~~ wait polling ~~~~~
[ 86.747966] ACPI : EC: ===== TASK (0) =====
[ 86.747977] ACPI : EC: EC_SC(R) = 0x20 SCI_EVT=1 BURST=0 CMD=0 IBF=0 OBF=0
[ 86.747978] ACPI : EC: EC_DATA(W) = 0x06
[ 86.747981] ACPI : EC: ~~~~~ wait polling ~~~~~
[ 86.751971] ACPI : EC: ~~~~~ wait polling ~~~~~
[ 86.755969] ACPI : EC: ===== TASK (0) =====
[ 86.755991] ACPI : EC: EC_SC(R) = 0x21 SCI_EVT=1 BURST=0 CMD=0 IBF=0 OBF=1
[ 86.755993] ACPI : EC: EC_DATA(R) = 0x03
[ 86.755994] ACPI : EC: ~~~~~ wait polling ~~~~~
[ 86.755995] ACPI : EC: ***** Command(RD_EC) stopped *****
[ 86.755996] ACPI : EC: 1: Decrease command
This patch corrects this by using time_before() instead in ec_guard():
[ 54.283146] ACPI: Waking up from system sleep state S3
[ 54.285414] ACPI : EC: 2: Increase command
[ 54.285415] ACPI : EC: ***** Command(RD_EC) started *****
[ 54.285416] ACPI : EC: ~~~~~ wait polling ~~~~~
[ 54.285417] ACPI : EC: ===== TASK (0) =====
[ 54.285424] ACPI : EC: EC_SC(R) = 0x20 SCI_EVT=1 BURST=0 CMD=0 IBF=0 OBF=0
[ 54.285425] ACPI : EC: EC_SC(W) = 0x80
[ 54.285427] ACPI : EC: ***** Event started *****
[ 54.285429] ACPI : EC: ~~~~~ wait polling ~~~~~
[ 54.287209] ACPI : EC: ===== TASK (0) =====
[ 54.287218] ACPI : EC: EC_SC(R) = 0x20 SCI_EVT=1 BURST=0 CMD=0 IBF=0 OBF=0
[ 54.287219] ACPI : EC: EC_DATA(W) = 0x06
[ 54.287222] ACPI : EC: ~~~~~ wait polling ~~~~~
[ 54.291190] ACPI : EC: ===== TASK (0) =====
[ 54.291210] ACPI : EC: EC_SC(R) = 0x21 SCI_EVT=1 BURST=0 CMD=0 IBF=0 OBF=1
[ 54.291213] ACPI : EC: EC_DATA(R) = 0x03
[ 54.291214] ACPI : EC: ~~~~~ wait polling ~~~~~
[ 54.291215] ACPI : EC: ***** Command(RD_EC) stopped *****
[ 54.291216] ACPI : EC: 1: Decrease command
After cleaning up all guarding logics, we have one single function
ec_guard() collecting all old, non-root-caused, hidden logics. Then we can
easily tune the logics in one place to respond to the bug reports.
Except the time_before() change, all other changes do not change the
behavior of the EC driver.
Link: https://bugzilla.kernel.org/show_bug.cgi?id=12011
Link: https://bugzilla.kernel.org/show_bug.cgi?id=20242
Link: https://bugzilla.kernel.org/show_bug.cgi?id=77431
Signed-off-by: Lv Zheng <lv.zheng@intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2015-05-15 14:16:42 +08:00
|
|
|
unsigned long timestamp;
|
2015-06-11 13:21:32 +08:00
|
|
|
unsigned long nr_pending_queries;
|
2017-01-20 16:42:48 +08:00
|
|
|
bool busy_polling;
|
|
|
|
unsigned int polling_guard;
|
2010-07-16 19:11:31 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
extern struct acpi_ec *first_ec;
|
|
|
|
|
2013-12-17 17:32:14 +08:00
|
|
|
/* If we find an EC via the ECDT, we need to keep a ptr to its context */
|
|
|
|
/* External interfaces use first EC only, so remember */
|
|
|
|
typedef int (*acpi_ec_query_func) (void *data);
|
|
|
|
|
2009-03-25 06:49:48 +08:00
|
|
|
int acpi_ec_init(void);
|
2009-03-14 02:08:26 +08:00
|
|
|
int acpi_ec_ecdt_probe(void);
|
2016-06-03 10:26:12 +08:00
|
|
|
int acpi_ec_dsdt_probe(void);
|
2010-04-09 07:40:38 +08:00
|
|
|
void acpi_ec_block_transactions(void);
|
|
|
|
void acpi_ec_unblock_transactions(void);
|
2013-12-17 17:32:14 +08:00
|
|
|
int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit,
|
|
|
|
acpi_handle handle, acpi_ec_query_func func,
|
|
|
|
void *data);
|
|
|
|
void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit);
|
|
|
|
|
2017-07-20 09:43:12 +08:00
|
|
|
#ifdef CONFIG_PM_SLEEP
|
|
|
|
void acpi_ec_flush_work(void);
|
|
|
|
#endif
|
|
|
|
|
2009-03-14 02:08:26 +08:00
|
|
|
|
|
|
|
/*--------------------------------------------------------------------------
|
|
|
|
Suspend/Resume
|
|
|
|
-------------------------------------------------------------------------- */
|
2015-03-24 22:02:39 +08:00
|
|
|
#ifdef CONFIG_ACPI_SYSTEM_POWER_STATES_SUPPORT
|
ACPI / PM: Ignore spurious SCI wakeups from suspend-to-idle
The ACPI SCI (System Control Interrupt) is set up as a wakeup IRQ
during suspend-to-idle transitions and, consequently, any events
signaled through it wake up the system from that state. However,
on some systems some of the events signaled via the ACPI SCI while
suspended to idle should not cause the system to wake up. In fact,
quite often they should just be discarded.
Arguably, systems should not resume entirely on such events, but in
order to decide which events really should cause the system to resume
and which are spurious, it is necessary to resume up to the point
when ACPI SCIs are actually handled and processed, which is after
executing dpm_resume_noirq() in the system resume path.
For this reasons, add a loop around freeze_enter() in which the
platforms can process events signaled via multiplexed IRQ lines
like the ACPI SCI and add suspend-to-idle hooks that can be
used for this purpose to struct platform_freeze_ops.
In the ACPI case, the ->wake hook is used for checking if the SCI
has triggered while suspended and deferring the interrupt-induced
system wakeup until the events signaled through it are actually
processed sufficiently to decide whether or not the system should
resume. In turn, the ->sync hook allows all of the relevant event
queues to be flushed so as to prevent events from being missed due
to race conditions.
In addition to that, some ACPI code processing wakeup events needs
to be modified to use the "hard" version of wakeup triggers, so that
it will cause a system resume to happen on device-induced wakeup
events even if the "soft" mechanism to prevent the system from
suspending is not enabled. However, to preserve the existing
behavior with respect to suspend-to-RAM, this only is done in
the suspend-to-idle case and only if an SCI has occurred while
suspended.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2017-06-13 04:56:34 +08:00
|
|
|
extern bool acpi_s2idle_wakeup(void);
|
ACPI / sleep: EC-based wakeup from suspend-to-idle on recent systems
Some recent Dell laptops, including the XPS13 model numbers 9360 and
9365, cannot be woken up from suspend-to-idle by pressing the power
button which is unexpected and makes that feature less usable on
those systems. Moreover, on the 9365 ACPI S3 (suspend-to-RAM) is
not expected to be used at all (the OS these systems ship with never
exercises the ACPI S3 path in the firmware) and suspend-to-idle is
the only viable system suspend mechanism there.
The reason why the power button wakeup from suspend-to-idle doesn't
work on those systems is because their power button events are
signaled by the EC (Embedded Controller), whose GPE (General Purpose
Event) line is disabled during suspend-to-idle transitions in Linux.
That is done on purpose, because in general the EC tends to be noisy
for various reasons (battery and thermal updates and similar, for
example) and all events signaled by it would kick the CPUs out of
deep idle states while in suspend-to-idle, which effectively might
defeat its purpose.
Of course, on the Dell systems in question the EC GPE must be enabled
during suspend-to-idle transitions for the button press events to
be signaled while suspended at all, but fortunately there is a way
out of this puzzle.
First of all, those systems have the ACPI_FADT_LOW_POWER_S0 flag set
in their ACPI tables, which means that the OS is expected to prefer
the "low power S0 idle" system state over ACPI S3 on them. That
causes the most recent versions of other OSes to simply ignore ACPI
S3 on those systems, so it is reasonable to expect that it should not
be necessary to block GPEs during suspend-to-idle on them.
Second, in addition to that, the systems in question provide a special
firmware interface that can be used to indicate to the platform that
the OS is transitioning into a system-wide low-power state in which
certain types of activity are not desirable or that it is leaving
such a state and that (in principle) should allow the platform to
adjust its operation mode accordingly.
That interface is a special _DSM object under a System Power
Management Controller device (PNP0D80). The expected way to use it
is to invoke function 0 from it on system initialization, functions
3 and 5 during suspend transitions and functions 4 and 6 during
resume transitions (to reverse the actions carried out by the
former). In particular, function 5 from the "Low-Power S0" device
_DSM is expected to cause the platform to put itself into a low-power
operation mode which should include making the EC less verbose (so to
speak). Next, on resume, function 6 switches the platform back to
the "working-state" operation mode.
In accordance with the above, modify the ACPI suspend-to-idle code
to look for the "Low-Power S0" _DSM interface on platforms with the
ACPI_FADT_LOW_POWER_S0 flag set in the ACPI tables. If it's there,
use it during suspend-to-idle transitions as prescribed and avoid
changing the GPE configuration in that case. [That should reflect
what the most recent versions of other OSes do.]
Also modify the ACPI EC driver to make it handle events during
suspend-to-idle in the usual way if the "Low-Power S0" _DSM interface
is going to be used to make the power button events work while
suspended on the Dell machines mentioned above
Link: http://www.uefi.org/sites/default/files/resources/Intel_ACPI_Low_Power_S0_Idle.pdf
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2017-06-23 21:24:32 +08:00
|
|
|
extern bool acpi_sleep_no_ec_events(void);
|
2009-03-14 02:08:26 +08:00
|
|
|
extern int acpi_sleep_init(void);
|
2015-03-24 22:02:39 +08:00
|
|
|
#else
|
ACPI / PM: Ignore spurious SCI wakeups from suspend-to-idle
The ACPI SCI (System Control Interrupt) is set up as a wakeup IRQ
during suspend-to-idle transitions and, consequently, any events
signaled through it wake up the system from that state. However,
on some systems some of the events signaled via the ACPI SCI while
suspended to idle should not cause the system to wake up. In fact,
quite often they should just be discarded.
Arguably, systems should not resume entirely on such events, but in
order to decide which events really should cause the system to resume
and which are spurious, it is necessary to resume up to the point
when ACPI SCIs are actually handled and processed, which is after
executing dpm_resume_noirq() in the system resume path.
For this reasons, add a loop around freeze_enter() in which the
platforms can process events signaled via multiplexed IRQ lines
like the ACPI SCI and add suspend-to-idle hooks that can be
used for this purpose to struct platform_freeze_ops.
In the ACPI case, the ->wake hook is used for checking if the SCI
has triggered while suspended and deferring the interrupt-induced
system wakeup until the events signaled through it are actually
processed sufficiently to decide whether or not the system should
resume. In turn, the ->sync hook allows all of the relevant event
queues to be flushed so as to prevent events from being missed due
to race conditions.
In addition to that, some ACPI code processing wakeup events needs
to be modified to use the "hard" version of wakeup triggers, so that
it will cause a system resume to happen on device-induced wakeup
events even if the "soft" mechanism to prevent the system from
suspending is not enabled. However, to preserve the existing
behavior with respect to suspend-to-RAM, this only is done in
the suspend-to-idle case and only if an SCI has occurred while
suspended.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2017-06-13 04:56:34 +08:00
|
|
|
static inline bool acpi_s2idle_wakeup(void) { return false; }
|
ACPI / sleep: EC-based wakeup from suspend-to-idle on recent systems
Some recent Dell laptops, including the XPS13 model numbers 9360 and
9365, cannot be woken up from suspend-to-idle by pressing the power
button which is unexpected and makes that feature less usable on
those systems. Moreover, on the 9365 ACPI S3 (suspend-to-RAM) is
not expected to be used at all (the OS these systems ship with never
exercises the ACPI S3 path in the firmware) and suspend-to-idle is
the only viable system suspend mechanism there.
The reason why the power button wakeup from suspend-to-idle doesn't
work on those systems is because their power button events are
signaled by the EC (Embedded Controller), whose GPE (General Purpose
Event) line is disabled during suspend-to-idle transitions in Linux.
That is done on purpose, because in general the EC tends to be noisy
for various reasons (battery and thermal updates and similar, for
example) and all events signaled by it would kick the CPUs out of
deep idle states while in suspend-to-idle, which effectively might
defeat its purpose.
Of course, on the Dell systems in question the EC GPE must be enabled
during suspend-to-idle transitions for the button press events to
be signaled while suspended at all, but fortunately there is a way
out of this puzzle.
First of all, those systems have the ACPI_FADT_LOW_POWER_S0 flag set
in their ACPI tables, which means that the OS is expected to prefer
the "low power S0 idle" system state over ACPI S3 on them. That
causes the most recent versions of other OSes to simply ignore ACPI
S3 on those systems, so it is reasonable to expect that it should not
be necessary to block GPEs during suspend-to-idle on them.
Second, in addition to that, the systems in question provide a special
firmware interface that can be used to indicate to the platform that
the OS is transitioning into a system-wide low-power state in which
certain types of activity are not desirable or that it is leaving
such a state and that (in principle) should allow the platform to
adjust its operation mode accordingly.
That interface is a special _DSM object under a System Power
Management Controller device (PNP0D80). The expected way to use it
is to invoke function 0 from it on system initialization, functions
3 and 5 during suspend transitions and functions 4 and 6 during
resume transitions (to reverse the actions carried out by the
former). In particular, function 5 from the "Low-Power S0" device
_DSM is expected to cause the platform to put itself into a low-power
operation mode which should include making the EC less verbose (so to
speak). Next, on resume, function 6 switches the platform back to
the "working-state" operation mode.
In accordance with the above, modify the ACPI suspend-to-idle code
to look for the "Low-Power S0" _DSM interface on platforms with the
ACPI_FADT_LOW_POWER_S0 flag set in the ACPI tables. If it's there,
use it during suspend-to-idle transitions as prescribed and avoid
changing the GPE configuration in that case. [That should reflect
what the most recent versions of other OSes do.]
Also modify the ACPI EC driver to make it handle events during
suspend-to-idle in the usual way if the "Low-Power S0" _DSM interface
is going to be used to make the power button events work while
suspended on the Dell machines mentioned above
Link: http://www.uefi.org/sites/default/files/resources/Intel_ACPI_Low_Power_S0_Idle.pdf
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2017-06-23 21:24:32 +08:00
|
|
|
static inline bool acpi_sleep_no_ec_events(void) { return true; }
|
2015-03-24 22:02:39 +08:00
|
|
|
static inline int acpi_sleep_init(void) { return -ENXIO; }
|
|
|
|
#endif
|
2009-03-25 06:50:14 +08:00
|
|
|
|
|
|
|
#ifdef CONFIG_ACPI_SLEEP
|
2015-09-11 22:49:22 +08:00
|
|
|
void acpi_sleep_proc_init(void);
|
2011-01-07 08:43:44 +08:00
|
|
|
int suspend_nvs_alloc(void);
|
|
|
|
void suspend_nvs_free(void);
|
|
|
|
int suspend_nvs_save(void);
|
|
|
|
void suspend_nvs_restore(void);
|
2009-03-25 06:50:14 +08:00
|
|
|
#else
|
2015-09-11 22:49:22 +08:00
|
|
|
static inline void acpi_sleep_proc_init(void) {}
|
2011-01-07 08:43:44 +08:00
|
|
|
static inline int suspend_nvs_alloc(void) { return 0; }
|
|
|
|
static inline void suspend_nvs_free(void) {}
|
2011-01-13 05:03:20 +08:00
|
|
|
static inline int suspend_nvs_save(void) { return 0; }
|
2011-01-07 08:43:44 +08:00
|
|
|
static inline void suspend_nvs_restore(void) {}
|
2009-03-25 06:50:14 +08:00
|
|
|
#endif
|
2010-07-16 19:11:31 +08:00
|
|
|
|
ACPI: Add support for device specific properties
Device Tree is used in many embedded systems to describe the system
configuration to the OS. It supports attaching properties or name-value
pairs to the devices it describe. With these properties one can pass
additional information to the drivers that would not be available
otherwise.
ACPI is another configuration mechanism (among other things) typically
seen, but not limited to, x86 machines. ACPI allows passing arbitrary
data from methods but there has not been mechanism equivalent to Device
Tree until the introduction of _DSD in the recent publication of the
ACPI 5.1 specification.
In order to facilitate ACPI usage in systems where Device Tree is
typically used, it would be beneficial to standardize a way to retrieve
Device Tree style properties from ACPI devices, which is what we do in
this patch.
If a given device described in ACPI namespace wants to export properties it
must implement _DSD method (Device Specific Data, introduced with ACPI 5.1)
that returns the properties in a package of packages. For example:
Name (_DSD, Package () {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package () {"name1", <VALUE1>},
Package () {"name2", <VALUE2>},
...
}
})
The UUID reserved for properties is daffd814-6eba-4d8c-8a91-bc9bbf4aa301
and is documented in the ACPI 5.1 companion document called "_DSD
Implementation Guide" [1], [2].
We add several helper functions that can be used to extract these
properties and convert them to different Linux data types.
The ultimate goal is that we only have one device property API that
retrieves the requested properties from Device Tree or from ACPI
transparent to the caller.
[1] http://www.uefi.org/sites/default/files/resources/_DSD-implementation-guide-toplevel.htm
[2] http://www.uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pdf
Reviewed-by: Hanjun Guo <hanjun.guo@linaro.org>
Reviewed-by: Josh Triplett <josh@joshtriplett.org>
Reviewed-by: Grant Likely <grant.likely@linaro.org>
Signed-off-by: Darren Hart <dvhart@linux.intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2014-10-21 19:33:55 +08:00
|
|
|
/*--------------------------------------------------------------------------
|
|
|
|
Device properties
|
|
|
|
-------------------------------------------------------------------------- */
|
2015-05-22 10:24:34 +08:00
|
|
|
#define ACPI_DT_NAMESPACE_HID "PRP0001"
|
|
|
|
|
ACPI: Add support for device specific properties
Device Tree is used in many embedded systems to describe the system
configuration to the OS. It supports attaching properties or name-value
pairs to the devices it describe. With these properties one can pass
additional information to the drivers that would not be available
otherwise.
ACPI is another configuration mechanism (among other things) typically
seen, but not limited to, x86 machines. ACPI allows passing arbitrary
data from methods but there has not been mechanism equivalent to Device
Tree until the introduction of _DSD in the recent publication of the
ACPI 5.1 specification.
In order to facilitate ACPI usage in systems where Device Tree is
typically used, it would be beneficial to standardize a way to retrieve
Device Tree style properties from ACPI devices, which is what we do in
this patch.
If a given device described in ACPI namespace wants to export properties it
must implement _DSD method (Device Specific Data, introduced with ACPI 5.1)
that returns the properties in a package of packages. For example:
Name (_DSD, Package () {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package () {"name1", <VALUE1>},
Package () {"name2", <VALUE2>},
...
}
})
The UUID reserved for properties is daffd814-6eba-4d8c-8a91-bc9bbf4aa301
and is documented in the ACPI 5.1 companion document called "_DSD
Implementation Guide" [1], [2].
We add several helper functions that can be used to extract these
properties and convert them to different Linux data types.
The ultimate goal is that we only have one device property API that
retrieves the requested properties from Device Tree or from ACPI
transparent to the caller.
[1] http://www.uefi.org/sites/default/files/resources/_DSD-implementation-guide-toplevel.htm
[2] http://www.uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pdf
Reviewed-by: Hanjun Guo <hanjun.guo@linaro.org>
Reviewed-by: Josh Triplett <josh@joshtriplett.org>
Reviewed-by: Grant Likely <grant.likely@linaro.org>
Signed-off-by: Darren Hart <dvhart@linux.intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2014-10-21 19:33:55 +08:00
|
|
|
void acpi_init_properties(struct acpi_device *adev);
|
|
|
|
void acpi_free_properties(struct acpi_device *adev);
|
|
|
|
|
ACPI / property: Support Apple _DSM properties
While the rest of the world has standardized on _DSD as the way to store
device properties in AML (introduced with ACPI 5.1 in 2014), Apple has
been using a custom _DSM to achieve the same for much longer (ever since
they switched from DeviceTree-based PowerPC to Intel in 2005, verified
with MacOS X 10.4.11).
The theory of operation on macOS is as follows: AppleACPIPlatform.kext
invokes mergeEFIproperties() and mergeDSMproperties() for each device to
merge properties conveyed by EFI drivers as well as properties stored in
AML into the I/O Kit registry from which they can be retrieved by
drivers. We've been supporting EFI properties since commit 58c5475aba67
("x86/efi: Retrieve and assign Apple device properties"). The present
commit adds support for _DSM properties, thereby completing our support
for Apple device properties. The _DSM properties are made available
under the primary fwnode, the EFI properties under the secondary fwnode.
So for devices which possess both property types, they can all be
elegantly accessed with the uniform API in <linux/property.h>.
Until recently we had no need to support _DSM properties, they contained
only uninteresting garbage. The situation has changed with MacBooks and
MacBook Pros introduced since 2015: Their keyboard is attached with SPI
instead of USB and the _CRS data which is necessary to initialize the
spi driver only contains valid information if OSPM responds "false" to
_OSI("Darwin"). If OSPM responds "true", _CRS is empty and the spi
driver fails to initialize. The rationale is very simple, Apple only
cares about macOS and Windows: On Windows, _CRS contains valid data,
whereas on macOS it is empty. Instead, macOS gleans the necessary data
from the _DSM properties.
Since Linux deliberately defaults to responding "true" to _OSI("Darwin"),
we need to emulate macOS' behaviour by initializing the spi driver with
data returned by the _DSM.
An out-of-tree driver for the SPI keyboard exists which currently binds
to the ACPI device, invokes the _DSM, parses the returned package and
instantiates an SPI device with the data gleaned from the _DSM:
https://github.com/cb22/macbook12-spi-driver/commit/9a416d699ef4
https://github.com/cb22/macbook12-spi-driver/commit/0c34936ed9a1
By adding support for Apple's _DSM properties in generic ACPI code, the
out-of-tree driver will be able to register as a regular SPI driver,
significantly reducing its amount of code and improving its chances to
be mainlined.
The SPI keyboard will not be the only user of this commit: E.g. on the
MacBook8,1, the UART-attached Bluetooth device likewise returns empty
_CRS data if OSPM returns "true" to _OSI("Darwin").
The _DSM returns a Package whose format unfortunately deviates slightly
from the _DSD spec: The properties are marshalled up in a single Package
as alternating key/value elements, unlike _DSD which stores them as a
Package of 2-element Packages. The present commit therefore converts
the Package to _DSD format and the ACPI core can then treat the data as
if Apple would follow the standard.
Well, except for one small annoyance: The properties returned by the
_DSM only ever have one of two types, Integer or Buffer. The former is
retrievable as usual with device_property_read_u64(), but the latter is
not part of the _DSD spec and it is not possible to retrieve Buffer
properties with the device_property_read_*() functions due to the type
checking performed in drivers/acpi/property.c. It is however possible
to retrieve them with acpi_dev_get_property(). Apple is using the
Buffer type somewhat sloppily to store null-terminated strings but also
integers. The real data type is not distinguishable by the ACPI core
and the onus is on the caller to use the contents of the Buffer in an
appropriate way.
In case Apple moves to _DSD in the future, this commit first checks for
_DSD and falls back to _DSM only if _DSD is not found.
Tested-by: Ronald Tschalär <ronald@innovation.ch>
Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Lukas Wunner <lukas@wunner.de>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2017-08-01 20:10:41 +08:00
|
|
|
#ifdef CONFIG_X86
|
|
|
|
void acpi_extract_apple_properties(struct acpi_device *adev);
|
|
|
|
#else
|
|
|
|
static inline void acpi_extract_apple_properties(struct acpi_device *adev) {}
|
|
|
|
#endif
|
|
|
|
|
2016-09-20 20:30:51 +08:00
|
|
|
/*--------------------------------------------------------------------------
|
|
|
|
Watchdog
|
|
|
|
-------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
#ifdef CONFIG_ACPI_WATCHDOG
|
|
|
|
void acpi_watchdog_init(void);
|
|
|
|
#else
|
|
|
|
static inline void acpi_watchdog_init(void) {}
|
|
|
|
#endif
|
|
|
|
|
2010-07-16 19:11:31 +08:00
|
|
|
#endif /* _ACPI_INTERNAL_H_ */
|