Commit b659ea76 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

Merge branches 'acpi-scan', 'acpi-pm', 'acpi-power' and 'acpi-pci'

Merge ACPI device enumeration updates, ACPI power management updates
and PCI host bridge ACPI driver updates for 5.17-rc1:

 - Introduce acpi_fetch_acpi_dev() as a replacement for
   acpi_bus_get_device() and use it in the ACPI subsystem (Rafael
   Wysocki).

 - Avoid using _CID for device enumaration if _HID is missing or
   invalid (Rafael Wysocki).

 - Rework quirk handling during ACPI device enumeration and add some
   new quirks for known broken platforms (Hans de Goede).

 - Avoid unnecessary or redundant CPU cache flushing during system
   PM transitions (Kirill A. Shutemov).

 - Add PM debug messages related to power resources (Rafael Wysocki).

 - Fix kernel-doc comment in the PCI host bridge ACPI driver (Yang Li).

* acpi-scan:
  serdev: Do not instantiate serdevs on boards with known bogus DSDT entries
  i2c: acpi: Do not instantiate I2C-clients on boards with known bogus DSDT entries
  ACPI / x86: Add acpi_quirk_skip_[i2c_client|serdev]_enumeration() helpers
  ACPI: scan: Create platform device for BCM4752 and LNV4752 ACPI nodes
  ACPI: Use acpi_fetch_acpi_dev() instead of acpi_bus_get_device()
  ACPI: scan: Introduce acpi_fetch_acpi_dev()
  ACPI: scan: Do not add device IDs from _CID if _HID is not valid

* acpi-pm:
  ACPI: PM: Remove redundant cache flushing
  ACPI: PM: Avoid CPU cache flush when entering S4

* acpi-power:
  ACPI: PM: Emit debug messages when enabling/disabling wakeup power

* acpi-pci:
  PCI/ACPI: Fix acpi_pci_osc_control_set() kernel-doc comment
...@@ -1733,13 +1733,12 @@ acpi_video_bus_match(acpi_handle handle, u32 level, void *context, ...@@ -1733,13 +1733,12 @@ acpi_video_bus_match(acpi_handle handle, u32 level, void *context,
{ {
struct acpi_device *device = context; struct acpi_device *device = context;
struct acpi_device *sibling; struct acpi_device *sibling;
int result;
if (handle == device->handle) if (handle == device->handle)
return AE_CTRL_TERMINATE; return AE_CTRL_TERMINATE;
result = acpi_bus_get_device(handle, &sibling); sibling = acpi_fetch_acpi_dev(handle);
if (result) if (!sibling)
return AE_OK; return AE_OK;
if (!strcmp(acpi_device_name(sibling), ACPI_VIDEO_BUS_NAME)) if (!strcmp(acpi_device_name(sibling), ACPI_VIDEO_BUS_NAME))
......
...@@ -285,14 +285,12 @@ EXPORT_SYMBOL(acpi_device_set_power); ...@@ -285,14 +285,12 @@ EXPORT_SYMBOL(acpi_device_set_power);
int acpi_bus_set_power(acpi_handle handle, int state) int acpi_bus_set_power(acpi_handle handle, int state)
{ {
struct acpi_device *device; struct acpi_device *device = acpi_fetch_acpi_dev(handle);
int result;
result = acpi_bus_get_device(handle, &device); if (device)
if (result) return acpi_device_set_power(device, state);
return result;
return acpi_device_set_power(device, state); return -ENODEV;
} }
EXPORT_SYMBOL(acpi_bus_set_power); EXPORT_SYMBOL(acpi_bus_set_power);
...@@ -410,21 +408,20 @@ EXPORT_SYMBOL_GPL(acpi_device_update_power); ...@@ -410,21 +408,20 @@ EXPORT_SYMBOL_GPL(acpi_device_update_power);
int acpi_bus_update_power(acpi_handle handle, int *state_p) int acpi_bus_update_power(acpi_handle handle, int *state_p)
{ {
struct acpi_device *device; struct acpi_device *device = acpi_fetch_acpi_dev(handle);
int result;
result = acpi_bus_get_device(handle, &device); if (device)
return result ? result : acpi_device_update_power(device, state_p); return acpi_device_update_power(device, state_p);
return -ENODEV;
} }
EXPORT_SYMBOL_GPL(acpi_bus_update_power); EXPORT_SYMBOL_GPL(acpi_bus_update_power);
bool acpi_bus_power_manageable(acpi_handle handle) bool acpi_bus_power_manageable(acpi_handle handle)
{ {
struct acpi_device *device; struct acpi_device *device = acpi_fetch_acpi_dev(handle);
int result;
result = acpi_bus_get_device(handle, &device); return device && device->flags.power_manageable;
return result ? false : device->flags.power_manageable;
} }
EXPORT_SYMBOL(acpi_bus_power_manageable); EXPORT_SYMBOL(acpi_bus_power_manageable);
...@@ -543,11 +540,9 @@ acpi_status acpi_remove_pm_notifier(struct acpi_device *adev) ...@@ -543,11 +540,9 @@ acpi_status acpi_remove_pm_notifier(struct acpi_device *adev)
bool acpi_bus_can_wakeup(acpi_handle handle) bool acpi_bus_can_wakeup(acpi_handle handle)
{ {
struct acpi_device *device; struct acpi_device *device = acpi_fetch_acpi_dev(handle);
int result;
result = acpi_bus_get_device(handle, &device); return device && device->wakeup.flags.valid;
return result ? false : device->wakeup.flags.valid;
} }
EXPORT_SYMBOL(acpi_bus_can_wakeup); EXPORT_SYMBOL(acpi_bus_can_wakeup);
......
...@@ -489,9 +489,8 @@ static ssize_t docked_show(struct device *dev, ...@@ -489,9 +489,8 @@ static ssize_t docked_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct dock_station *dock_station = dev->platform_data; struct dock_station *dock_station = dev->platform_data;
struct acpi_device *adev = NULL; struct acpi_device *adev = acpi_fetch_acpi_dev(dock_station->handle);
acpi_bus_get_device(dock_station->handle, &adev);
return sysfs_emit(buf, "%u\n", acpi_device_enumerated(adev)); return sysfs_emit(buf, "%u\n", acpi_device_enumerated(adev));
} }
static DEVICE_ATTR_RO(docked); static DEVICE_ATTR_RO(docked);
......
...@@ -606,12 +606,10 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link) ...@@ -606,12 +606,10 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link)
int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering, int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
int *polarity, char **name) int *polarity, char **name)
{ {
int result; struct acpi_device *device = acpi_fetch_acpi_dev(handle);
struct acpi_device *device;
struct acpi_pci_link *link; struct acpi_pci_link *link;
result = acpi_bus_get_device(handle, &device); if (!device) {
if (result) {
acpi_handle_err(handle, "Invalid link device\n"); acpi_handle_err(handle, "Invalid link device\n");
return -1; return -1;
} }
...@@ -658,12 +656,10 @@ int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering, ...@@ -658,12 +656,10 @@ int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
*/ */
int acpi_pci_link_free_irq(acpi_handle handle) int acpi_pci_link_free_irq(acpi_handle handle)
{ {
struct acpi_device *device; struct acpi_device *device = acpi_fetch_acpi_dev(handle);
struct acpi_pci_link *link; struct acpi_pci_link *link;
acpi_status result;
result = acpi_bus_get_device(handle, &device); if (!device) {
if (result) {
acpi_handle_err(handle, "Invalid link device\n"); acpi_handle_err(handle, "Invalid link device\n");
return -1; return -1;
} }
......
...@@ -67,11 +67,10 @@ static struct acpi_scan_handler pci_root_handler = { ...@@ -67,11 +67,10 @@ static struct acpi_scan_handler pci_root_handler = {
*/ */
int acpi_is_root_bridge(acpi_handle handle) int acpi_is_root_bridge(acpi_handle handle)
{ {
struct acpi_device *device = acpi_fetch_acpi_dev(handle);
int ret; int ret;
struct acpi_device *device;
ret = acpi_bus_get_device(handle, &device); if (!device)
if (ret)
return 0; return 0;
ret = acpi_match_device_ids(device, root_device_ids); ret = acpi_match_device_ids(device, root_device_ids);
...@@ -215,11 +214,10 @@ static acpi_status acpi_pci_query_osc(struct acpi_pci_root *root, ...@@ -215,11 +214,10 @@ static acpi_status acpi_pci_query_osc(struct acpi_pci_root *root,
struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle) struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle)
{ {
struct acpi_device *device = acpi_fetch_acpi_dev(handle);
struct acpi_pci_root *root; struct acpi_pci_root *root;
struct acpi_device *device;
if (acpi_bus_get_device(handle, &device) || if (!device || acpi_match_device_ids(device, root_device_ids))
acpi_match_device_ids(device, root_device_ids))
return NULL; return NULL;
root = acpi_driver_data(device); root = acpi_driver_data(device);
...@@ -324,7 +322,7 @@ EXPORT_SYMBOL_GPL(acpi_get_pci_dev); ...@@ -324,7 +322,7 @@ EXPORT_SYMBOL_GPL(acpi_get_pci_dev);
* acpi_pci_osc_control_set - Request control of PCI root _OSC features. * acpi_pci_osc_control_set - Request control of PCI root _OSC features.
* @handle: ACPI handle of a PCI root bridge (or PCIe Root Complex). * @handle: ACPI handle of a PCI root bridge (or PCIe Root Complex).
* @mask: Mask of _OSC bits to request control of, place to store control mask. * @mask: Mask of _OSC bits to request control of, place to store control mask.
* @req: Mask of _OSC bits the control of is essential to the caller. * @support: _OSC supported capability.
* *
* Run _OSC query for @mask and if that is successful, compare the returned * Run _OSC query for @mask and if that is successful, compare the returned
* mask of control bits with @req. If all of the @req bits are set in the * mask of control bits with @req. If all of the @req bits are set in the
......
...@@ -81,9 +81,9 @@ struct acpi_power_resource *to_power_resource(struct acpi_device *device) ...@@ -81,9 +81,9 @@ struct acpi_power_resource *to_power_resource(struct acpi_device *device)
static struct acpi_power_resource *acpi_power_get_context(acpi_handle handle) static struct acpi_power_resource *acpi_power_get_context(acpi_handle handle)
{ {
struct acpi_device *device; struct acpi_device *device = acpi_fetch_acpi_dev(handle);
if (acpi_bus_get_device(handle, &device)) if (!device)
return NULL; return NULL;
return to_power_resource(device); return to_power_resource(device);
...@@ -716,6 +716,9 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state) ...@@ -716,6 +716,9 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state)
mutex_lock(&acpi_device_lock); mutex_lock(&acpi_device_lock);
dev_dbg(&dev->dev, "Enabling wakeup power (count %d)\n",
dev->wakeup.prepare_count);
if (dev->wakeup.prepare_count++) if (dev->wakeup.prepare_count++)
goto out; goto out;
...@@ -734,8 +737,11 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state) ...@@ -734,8 +737,11 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state)
if (err) { if (err) {
acpi_power_off_list(&dev->wakeup.resources); acpi_power_off_list(&dev->wakeup.resources);
dev->wakeup.prepare_count = 0; dev->wakeup.prepare_count = 0;
goto out;
} }
dev_dbg(&dev->dev, "Wakeup power enabled\n");
out: out:
mutex_unlock(&acpi_device_lock); mutex_unlock(&acpi_device_lock);
return err; return err;
...@@ -757,6 +763,9 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev) ...@@ -757,6 +763,9 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev)
mutex_lock(&acpi_device_lock); mutex_lock(&acpi_device_lock);
dev_dbg(&dev->dev, "Disabling wakeup power (count %d)\n",
dev->wakeup.prepare_count);
/* Do nothing if wakeup power has not been enabled for this device. */ /* Do nothing if wakeup power has not been enabled for this device. */
if (dev->wakeup.prepare_count <= 0) if (dev->wakeup.prepare_count <= 0)
goto out; goto out;
...@@ -782,8 +791,11 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev) ...@@ -782,8 +791,11 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev)
if (err) { if (err) {
dev_err(&dev->dev, "Cannot turn off wakeup power resources\n"); dev_err(&dev->dev, "Cannot turn off wakeup power resources\n");
dev->wakeup.flags.valid = 0; dev->wakeup.flags.valid = 0;
goto out;
} }
dev_dbg(&dev->dev, "Wakeup power disabled\n");
out: out:
mutex_unlock(&acpi_device_lock); mutex_unlock(&acpi_device_lock);
return err; return err;
...@@ -916,15 +928,14 @@ static void acpi_power_add_resource_to_list(struct acpi_power_resource *resource ...@@ -916,15 +928,14 @@ static void acpi_power_add_resource_to_list(struct acpi_power_resource *resource
struct acpi_device *acpi_add_power_resource(acpi_handle handle) struct acpi_device *acpi_add_power_resource(acpi_handle handle)
{ {
struct acpi_device *device = acpi_fetch_acpi_dev(handle);
struct acpi_power_resource *resource; struct acpi_power_resource *resource;
struct acpi_device *device = NULL;
union acpi_object acpi_object; union acpi_object acpi_object;
struct acpi_buffer buffer = { sizeof(acpi_object), &acpi_object }; struct acpi_buffer buffer = { sizeof(acpi_object), &acpi_object };
acpi_status status; acpi_status status;
u8 state_dummy; u8 state_dummy;
int result; int result;
acpi_bus_get_device(handle, &device);
if (device) if (device)
return device; return device;
......
...@@ -98,8 +98,13 @@ static int acpi_soft_cpu_online(unsigned int cpu) ...@@ -98,8 +98,13 @@ static int acpi_soft_cpu_online(unsigned int cpu)
struct acpi_processor *pr = per_cpu(processors, cpu); struct acpi_processor *pr = per_cpu(processors, cpu);
struct acpi_device *device; struct acpi_device *device;
if (!pr || acpi_bus_get_device(pr->handle, &device)) if (!pr)
return 0;
device = acpi_fetch_acpi_dev(pr->handle);
if (!device)
return 0; return 0;
/* /*
* CPU got physically hotplugged and onlined for the first time: * CPU got physically hotplugged and onlined for the first time:
* Initialize missing things. * Initialize missing things.
...@@ -125,9 +130,8 @@ static int acpi_soft_cpu_online(unsigned int cpu) ...@@ -125,9 +130,8 @@ static int acpi_soft_cpu_online(unsigned int cpu)
static int acpi_soft_cpu_dead(unsigned int cpu) static int acpi_soft_cpu_dead(unsigned int cpu)
{ {
struct acpi_processor *pr = per_cpu(processors, cpu); struct acpi_processor *pr = per_cpu(processors, cpu);
struct acpi_device *device;
if (!pr || acpi_bus_get_device(pr->handle, &device)) if (!pr || !acpi_fetch_acpi_dev(pr->handle))
return 0; return 0;
acpi_processor_reevaluate_tstate(pr, true); acpi_processor_reevaluate_tstate(pr, true);
......
...@@ -1101,7 +1101,7 @@ static int acpi_processor_get_lpi_info(struct acpi_processor *pr) ...@@ -1101,7 +1101,7 @@ static int acpi_processor_get_lpi_info(struct acpi_processor *pr)
status = acpi_get_parent(handle, &pr_ahandle); status = acpi_get_parent(handle, &pr_ahandle);
while (ACPI_SUCCESS(status)) { while (ACPI_SUCCESS(status)) {
acpi_bus_get_device(pr_ahandle, &d); d = acpi_fetch_acpi_dev(pr_ahandle);
handle = pr_ahandle; handle = pr_ahandle;
if (strcmp(acpi_device_hid(d), ACPI_PROCESSOR_CONTAINER_HID)) if (strcmp(acpi_device_hid(d), ACPI_PROCESSOR_CONTAINER_HID))
......
...@@ -687,9 +687,9 @@ int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode, ...@@ -687,9 +687,9 @@ int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode,
if (index) if (index)
return -EINVAL; return -EINVAL;
ret = acpi_bus_get_device(obj->reference.handle, &device); device = acpi_fetch_acpi_dev(obj->reference.handle);
if (ret) if (!device)
return ret == -ENODEV ? -EINVAL : ret; return -EINVAL;
args->fwnode = acpi_fwnode_handle(device); args->fwnode = acpi_fwnode_handle(device);
args->nargs = 0; args->nargs = 0;
...@@ -719,9 +719,8 @@ int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode, ...@@ -719,9 +719,8 @@ int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode,
if (element->type == ACPI_TYPE_LOCAL_REFERENCE) { if (element->type == ACPI_TYPE_LOCAL_REFERENCE) {
struct fwnode_handle *ref_fwnode; struct fwnode_handle *ref_fwnode;
ret = acpi_bus_get_device(element->reference.handle, device = acpi_fetch_acpi_dev(element->reference.handle);
&device); if (!device)
if (ret)
return -EINVAL; return -EINVAL;
nargs = 0; nargs = 0;
......
...@@ -791,9 +791,9 @@ static acpi_status acpi_res_consumer_cb(acpi_handle handle, u32 depth, ...@@ -791,9 +791,9 @@ static acpi_status acpi_res_consumer_cb(acpi_handle handle, u32 depth,
{ {
struct resource *res = context; struct resource *res = context;
struct acpi_device **consumer = (struct acpi_device **) ret; struct acpi_device **consumer = (struct acpi_device **) ret;
struct acpi_device *adev; struct acpi_device *adev = acpi_fetch_acpi_dev(handle);
if (acpi_bus_get_device(handle, &adev)) if (!adev)
return AE_OK; return AE_OK;
if (acpi_dev_consumes_res(adev, res)) { if (acpi_dev_consumes_res(adev, res)) {
......
...@@ -135,12 +135,12 @@ bool acpi_scan_is_offline(struct acpi_device *adev, bool uevent) ...@@ -135,12 +135,12 @@ bool acpi_scan_is_offline(struct acpi_device *adev, bool uevent)
static acpi_status acpi_bus_offline(acpi_handle handle, u32 lvl, void *data, static acpi_status acpi_bus_offline(acpi_handle handle, u32 lvl, void *data,
void **ret_p) void **ret_p)
{ {
struct acpi_device *device = NULL; struct acpi_device *device = acpi_fetch_acpi_dev(handle);
struct acpi_device_physical_node *pn; struct acpi_device_physical_node *pn;
bool second_pass = (bool)data; bool second_pass = (bool)data;
acpi_status status = AE_OK; acpi_status status = AE_OK;
if (acpi_bus_get_device(handle, &device)) if (!device)
return AE_OK; return AE_OK;
if (device->handler && !device->handler->hotplug.enabled) { if (device->handler && !device->handler->hotplug.enabled) {
...@@ -180,10 +180,10 @@ static acpi_status acpi_bus_offline(acpi_handle handle, u32 lvl, void *data, ...@@ -180,10 +180,10 @@ static acpi_status acpi_bus_offline(acpi_handle handle, u32 lvl, void *data,
static acpi_status acpi_bus_online(acpi_handle handle, u32 lvl, void *data, static acpi_status acpi_bus_online(acpi_handle handle, u32 lvl, void *data,
void **ret_p) void **ret_p)
{ {
struct acpi_device *device = NULL; struct acpi_device *device = acpi_fetch_acpi_dev(handle);
struct acpi_device_physical_node *pn; struct acpi_device_physical_node *pn;
if (acpi_bus_get_device(handle, &device)) if (!device)
return AE_OK; return AE_OK;
mutex_lock(&device->physical_node_lock); mutex_lock(&device->physical_node_lock);
...@@ -599,6 +599,19 @@ int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device) ...@@ -599,6 +599,19 @@ int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device)
} }
EXPORT_SYMBOL(acpi_bus_get_device); EXPORT_SYMBOL(acpi_bus_get_device);
/**
* acpi_fetch_acpi_dev - Retrieve ACPI device object.
* @handle: ACPI handle associated with the requested ACPI device object.
*
* Return a pointer to the ACPI device object associated with @handle, if
* present, or NULL otherwise.
*/
struct acpi_device *acpi_fetch_acpi_dev(acpi_handle handle)
{
return handle_to_device(handle, NULL);
}
EXPORT_SYMBOL_GPL(acpi_fetch_acpi_dev);
static void get_acpi_device(void *dev) static void get_acpi_device(void *dev)
{ {
acpi_dev_get(dev); acpi_dev_get(dev);
...@@ -799,7 +812,7 @@ static const char * const acpi_ignore_dep_ids[] = { ...@@ -799,7 +812,7 @@ static const char * const acpi_ignore_dep_ids[] = {
static struct acpi_device *acpi_bus_get_parent(acpi_handle handle) static struct acpi_device *acpi_bus_get_parent(acpi_handle handle)
{ {
struct acpi_device *device = NULL; struct acpi_device *device;
acpi_status status; acpi_status status;
/* /*
...@@ -814,7 +827,9 @@ static struct acpi_device *acpi_bus_get_parent(acpi_handle handle) ...@@ -814,7 +827,9 @@ static struct acpi_device *acpi_bus_get_parent(acpi_handle handle)
status = acpi_get_parent(handle, &handle); status = acpi_get_parent(handle, &handle);
if (ACPI_FAILURE(status)) if (ACPI_FAILURE(status))
return status == AE_NULL_ENTRY ? NULL : acpi_root; return status == AE_NULL_ENTRY ? NULL : acpi_root;
} while (acpi_bus_get_device(handle, &device));
device = acpi_fetch_acpi_dev(handle);
} while (!device);
return device; return device;
} }
...@@ -1340,11 +1355,11 @@ static void acpi_set_pnp_ids(acpi_handle handle, struct acpi_device_pnp *pnp, ...@@ -1340,11 +1355,11 @@ static void acpi_set_pnp_ids(acpi_handle handle, struct acpi_device_pnp *pnp,
if (info->valid & ACPI_VALID_HID) { if (info->valid & ACPI_VALID_HID) {
acpi_add_id(pnp, info->hardware_id.string); acpi_add_id(pnp, info->hardware_id.string);
pnp->type.platform_id = 1; pnp->type.platform_id = 1;
} if (info->valid & ACPI_VALID_CID) {
if (info->valid & ACPI_VALID_CID) { cid_list = &info->compatible_id_list;
cid_list = &info->compatible_id_list; for (i = 0; i < cid_list->count; i++)
for (i = 0; i < cid_list->count; i++) acpi_add_id(pnp, cid_list->ids[i].string);
acpi_add_id(pnp, cid_list->ids[i].string); }
} }
if (info->valid & ACPI_VALID_ADR) { if (info->valid & ACPI_VALID_ADR) {
pnp->bus_address = info->address; pnp->bus_address = info->address;
...@@ -1695,6 +1710,7 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device) ...@@ -1695,6 +1710,7 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device)
{ {
struct list_head resource_list; struct list_head resource_list;
bool is_serial_bus_slave = false; bool is_serial_bus_slave = false;
static const struct acpi_device_id ignore_serial_bus_ids[] = {
/* /*
* These devices have multiple I2cSerialBus resources and an i2c-client * These devices have multiple I2cSerialBus resources and an i2c-client
* must be instantiated for each, each with its own i2c_device_id. * must be instantiated for each, each with its own i2c_device_id.
...@@ -1703,11 +1719,18 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device) ...@@ -1703,11 +1719,18 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device)
* drivers/platform/x86/i2c-multi-instantiate.c driver, which knows * drivers/platform/x86/i2c-multi-instantiate.c driver, which knows
* which i2c_device_id to use for each resource. * which i2c_device_id to use for each resource.
*/ */
static const struct acpi_device_id i2c_multi_instantiate_ids[] = {
{"BSG1160", }, {"BSG1160", },
{"BSG2150", }, {"BSG2150", },
{"INT33FE", }, {"INT33FE", },
{"INT3515", }, {"INT3515", },
/*
* HIDs of device with an UartSerialBusV2 resource for which userspace
* expects a regular tty cdev to be created (instead of the in kernel
* serdev) and which have a kernel driver which expects a platform_dev
* such as the rfkill-gpio driver.
*/
{"BCM4752", },
{"LNV4752", },
{} {}
}; };
...@@ -1721,8 +1744,7 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device) ...@@ -1721,8 +1744,7 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device)
fwnode_property_present(&device->fwnode, "baud"))) fwnode_property_present(&device->fwnode, "baud")))
return true; return true;
/* Instantiate a pdev for the i2c-multi-instantiate drv to bind to */ if (!acpi_match_device_ids(device, ignore_serial_bus_ids))
if (!acpi_match_device_ids(device, i2c_multi_instantiate_ids))
return false; return false;
INIT_LIST_HEAD(&resource_list); INIT_LIST_HEAD(&resource_list);
...@@ -2003,11 +2025,10 @@ static bool acpi_bus_scan_second_pass; ...@@ -2003,11 +2025,10 @@ static bool acpi_bus_scan_second_pass;
static acpi_status acpi_bus_check_add(acpi_handle handle, bool check_dep, static acpi_status acpi_bus_check_add(acpi_handle handle, bool check_dep,
struct acpi_device **adev_p) struct acpi_device **adev_p)
{ {
struct acpi_device *device = NULL; struct acpi_device *device = acpi_fetch_acpi_dev(handle);
acpi_object_type acpi_type; acpi_object_type acpi_type;
int type; int type;
acpi_bus_get_device(handle, &device);
if (device) if (device)
goto out; goto out;
...@@ -2548,8 +2569,8 @@ int __init acpi_scan_init(void) ...@@ -2548,8 +2569,8 @@ int __init acpi_scan_init(void)
if (result) if (result)
goto out; goto out;
result = acpi_bus_get_device(ACPI_ROOT_OBJECT, &acpi_root); acpi_root = acpi_fetch_acpi_dev(ACPI_ROOT_OBJECT);
if (result) if (!acpi_root)
goto out; goto out;
/* Fixed feature devices do not exist on HW-reduced platform */ /* Fixed feature devices do not exist on HW-reduced platform */
......
...@@ -73,7 +73,6 @@ static int acpi_sleep_prepare(u32 acpi_state) ...@@ -73,7 +73,6 @@ static int acpi_sleep_prepare(u32 acpi_state)
acpi_set_waking_vector(acpi_wakeup_address); acpi_set_waking_vector(acpi_wakeup_address);
} }
ACPI_FLUSH_CPU_CACHE();
#endif #endif
pr_info("Preparing to enter system sleep state S%d\n", acpi_state); pr_info("Preparing to enter system sleep state S%d\n", acpi_state);
acpi_enable_wakeup_devices(acpi_state); acpi_enable_wakeup_devices(acpi_state);
...@@ -566,8 +565,6 @@ static int acpi_suspend_enter(suspend_state_t pm_state) ...@@ -566,8 +565,6 @@ static int acpi_suspend_enter(suspend_state_t pm_state)
u32 acpi_state = acpi_target_sleep_state; u32 acpi_state = acpi_target_sleep_state;
int error; int error;
ACPI_FLUSH_CPU_CACHE();
trace_suspend_resume(TPS("acpi_suspend"), acpi_state, true); trace_suspend_resume(TPS("acpi_suspend"), acpi_state, true);
switch (acpi_state) { switch (acpi_state) {
case ACPI_STATE_S1: case ACPI_STATE_S1:
...@@ -903,8 +900,6 @@ static int acpi_hibernation_enter(void) ...@@ -903,8 +900,6 @@ static int acpi_hibernation_enter(void)
{ {
acpi_status status = AE_OK; acpi_status status = AE_OK;
ACPI_FLUSH_CPU_CACHE();
/* This shouldn't return. If it returns, we have a problem */ /* This shouldn't return. If it returns, we have a problem */
status = acpi_enter_sleep_state(ACPI_STATE_S4); status = acpi_enter_sleep_state(ACPI_STATE_S4);
/* Reprogram control registers */ /* Reprogram control registers */
......
...@@ -697,7 +697,6 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal, ...@@ -697,7 +697,6 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
struct acpi_device *device = cdev->devdata; struct acpi_device *device = cdev->devdata;
struct acpi_thermal *tz = thermal->devdata; struct acpi_thermal *tz = thermal->devdata;
struct acpi_device *dev; struct acpi_device *dev;
acpi_status status;
acpi_handle handle; acpi_handle handle;
int i; int i;
int j; int j;
...@@ -715,8 +714,8 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal, ...@@ -715,8 +714,8 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
for (i = 0; i < tz->trips.passive.devices.count; for (i = 0; i < tz->trips.passive.devices.count;
i++) { i++) {
handle = tz->trips.passive.devices.handles[i]; handle = tz->trips.passive.devices.handles[i];
status = acpi_bus_get_device(handle, &dev); dev = acpi_fetch_acpi_dev(handle);
if (ACPI_FAILURE(status) || dev != device) if (dev != device)
continue; continue;
if (bind) if (bind)
result = result =
...@@ -741,8 +740,8 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal, ...@@ -741,8 +740,8 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
j < tz->trips.active[i].devices.count; j < tz->trips.active[i].devices.count;
j++) { j++) {
handle = tz->trips.active[i].devices.handles[j]; handle = tz->trips.active[i].devices.handles[j];
status = acpi_bus_get_device(handle, &dev); dev = acpi_fetch_acpi_dev(handle);
if (ACPI_FAILURE(status) || dev != device) if (dev != device)
continue; continue;
if (bind) if (bind)
result = thermal_zone_bind_cooling_device result = thermal_zone_bind_cooling_device
......
...@@ -59,18 +59,16 @@ static void acpi_video_parse_cmdline(void) ...@@ -59,18 +59,16 @@ static void acpi_video_parse_cmdline(void)
static acpi_status static acpi_status
find_video(acpi_handle handle, u32 lvl, void *context, void **rv) find_video(acpi_handle handle, u32 lvl, void *context, void **rv)
{ {
struct acpi_device *acpi_dev = acpi_fetch_acpi_dev(handle);
long *cap = context; long *cap = context;
struct pci_dev *dev; struct pci_dev *dev;
struct acpi_device *acpi_dev;
static const struct acpi_device_id video_ids[] = { static const struct acpi_device_id video_ids[] = {
{ACPI_VIDEO_HID, 0}, {ACPI_VIDEO_HID, 0},
{"", 0}, {"", 0},
}; };
if (acpi_bus_get_device(handle, &acpi_dev))
return AE_OK;
if (!acpi_match_device_ids(acpi_dev, video_ids)) { if (acpi_dev && !acpi_match_device_ids(acpi_dev, video_ids)) {
dev = acpi_get_pci_dev(handle); dev = acpi_get_pci_dev(handle);
if (!dev) if (!dev)
return AE_OK; return AE_OK;
......
...@@ -293,9 +293,9 @@ static void lpi_check_constraints(void) ...@@ -293,9 +293,9 @@ static void lpi_check_constraints(void)
for (i = 0; i < lpi_constraints_table_size; ++i) { for (i = 0; i < lpi_constraints_table_size; ++i) {
acpi_handle handle = lpi_constraints_table[i].handle; acpi_handle handle = lpi_constraints_table[i].handle;
struct acpi_device *adev; struct acpi_device *adev = acpi_fetch_acpi_dev(handle);
if (!handle || acpi_bus_get_device(handle, &adev)) if (!adev)
continue; continue;
acpi_handle_debug(handle, acpi_handle_debug(handle,
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/dmi.h> #include <linux/dmi.h>
#include <linux/platform_device.h>
#include <asm/cpu_device_id.h> #include <asm/cpu_device_id.h>
#include <asm/intel-family.h> #include <asm/intel-family.h>
#include "../internal.h" #include "../internal.h"
...@@ -160,3 +161,113 @@ bool force_storage_d3(void) ...@@ -160,3 +161,113 @@ bool force_storage_d3(void)
{ {
return x86_match_cpu(storage_d3_cpu_ids); return x86_match_cpu(storage_d3_cpu_ids);
} }
#if IS_ENABLED(CONFIG_X86_ANDROID_TABLETS)
/*
* x86 ACPI boards which ship with only Android as their factory image usually
* declare a whole bunch of bogus I2C devices in their ACPI tables and sometimes
* there are issues with serdev devices on these boards too, e.g. the resource
* points to the wrong serdev_controller.
*
* Instantiating I2C / serdev devs for these bogus devs causes various issues,
* e.g. GPIO/IRQ resource conflicts because sometimes drivers do bind to them.
* The Android x86 kernel fork shipped on these devices has some special code
* to remove the bogus I2C clients (and AFAICT serdevs are ignored completely).
*
* The acpi_quirk_skip_*_enumeration() functions below are used by the I2C or
* serdev code to skip instantiating any I2C or serdev devs on broken boards.
*
* In case of I2C an exception is made for HIDs on the i2c_acpi_known_good_ids
* list. These are known to always be correct (and in case of the audio-codecs
* the drivers heavily rely on the codec being enumerated through ACPI).
*
* Note these boards typically do actually have I2C and serdev devices,
* just different ones then the ones described in their DSDT. The devices
* which are actually present are manually instantiated by the
* drivers/platform/x86/x86-android-tablets.c kernel module.
*/
#define ACPI_QUIRK_SKIP_I2C_CLIENTS BIT(0)
#define ACPI_QUIRK_UART1_TTY_UART2_SKIP BIT(1)
static const struct dmi_system_id acpi_skip_serial_bus_enumeration_ids[] = {
{
.matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ME176C"),
},
.driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS |
ACPI_QUIRK_UART1_TTY_UART2_SKIP),
},
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_PRODUCT_NAME, "TF103C"),
},
.driver_data = (void *)ACPI_QUIRK_SKIP_I2C_CLIENTS,
},
{
/* Whitelabel (sold as various brands) TM800A550L */
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
/* Above strings are too generic, also match on BIOS version */
DMI_MATCH(DMI_BIOS_VERSION, "ZY-8-BI-PX4S70VTR400-X423B-005-D"),
},
.driver_data = (void *)ACPI_QUIRK_SKIP_I2C_CLIENTS,
},
{}
};
static const struct acpi_device_id i2c_acpi_known_good_ids[] = {
{ "10EC5640", 0 }, /* RealTek ALC5640 audio codec */
{ "INT33F4", 0 }, /* X-Powers AXP288 PMIC */
{ "INT33FD", 0 }, /* Intel Crystal Cove PMIC */
{ "NPCE69A", 0 }, /* Asus Transformer keyboard dock */
{}
};
bool acpi_quirk_skip_i2c_client_enumeration(struct acpi_device *adev)
{
const struct dmi_system_id *dmi_id;
long quirks;
dmi_id = dmi_first_match(acpi_skip_serial_bus_enumeration_ids);
if (!dmi_id)
return false;
quirks = (unsigned long)dmi_id->driver_data;
if (!(quirks & ACPI_QUIRK_SKIP_I2C_CLIENTS))
return false;
return acpi_match_device_ids(adev, i2c_acpi_known_good_ids);
}
EXPORT_SYMBOL_GPL(acpi_quirk_skip_i2c_client_enumeration);
int acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *skip)
{
struct acpi_device *adev = ACPI_COMPANION(controller_parent);
const struct dmi_system_id *dmi_id;
long quirks = 0;
*skip = false;
/* !dev_is_platform() to not match on PNP enumerated debug UARTs */
if (!adev || !adev->pnp.unique_id || !dev_is_platform(controller_parent))
return 0;
dmi_id = dmi_first_match(acpi_skip_serial_bus_enumeration_ids);
if (dmi_id)
quirks = (unsigned long)dmi_id->driver_data;
if (quirks & ACPI_QUIRK_UART1_TTY_UART2_SKIP) {
if (!strcmp(adev->pnp.unique_id, "1"))
return -ENODEV; /* Create tty cdev instead of serdev */
if (!strcmp(adev->pnp.unique_id, "2"))
*skip = true;
}
return 0;
}
EXPORT_SYMBOL_GPL(acpi_quirk_skip_serdev_enumeration);
#endif
...@@ -254,6 +254,13 @@ static void i2c_acpi_register_device(struct i2c_adapter *adapter, ...@@ -254,6 +254,13 @@ static void i2c_acpi_register_device(struct i2c_adapter *adapter,
struct acpi_device *adev, struct acpi_device *adev,
struct i2c_board_info *info) struct i2c_board_info *info)
{ {
/*
* Skip registration on boards where the ACPI tables are
* known to contain bogus I2C devices.
*/
if (acpi_quirk_skip_i2c_client_enumeration(adev))
return;
adev->power.flags.ignore_parent = true; adev->power.flags.ignore_parent = true;
acpi_device_set_enumerated(adev); acpi_device_set_enumerated(adev);
......
...@@ -727,10 +727,24 @@ static acpi_status acpi_serdev_add_device(acpi_handle handle, u32 level, ...@@ -727,10 +727,24 @@ static acpi_status acpi_serdev_add_device(acpi_handle handle, u32 level,
static int acpi_serdev_register_devices(struct serdev_controller *ctrl) static int acpi_serdev_register_devices(struct serdev_controller *ctrl)
{ {
acpi_status status; acpi_status status;
bool skip;
int ret;
if (!has_acpi_companion(ctrl->dev.parent)) if (!has_acpi_companion(ctrl->dev.parent))
return -ENODEV; return -ENODEV;
/*
* Skip registration on boards where the ACPI tables are known to
* contain buggy devices. Note serdev_controller_add() must still
* succeed in this case, so that the proper serdev devices can be
* added "manually" later.
*/
ret = acpi_quirk_skip_serdev_enumeration(ctrl->dev.parent, &skip);
if (ret)
return ret;
if (skip)
return 0;
status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
SERDEV_ACPI_MAX_SCAN_DEPTH, SERDEV_ACPI_MAX_SCAN_DEPTH,
acpi_serdev_add_device, NULL, ctrl, NULL); acpi_serdev_add_device, NULL, ctrl, NULL);
......
...@@ -505,6 +505,7 @@ extern int unregister_acpi_notifier(struct notifier_block *); ...@@ -505,6 +505,7 @@ extern int unregister_acpi_notifier(struct notifier_block *);
*/ */
int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device); int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device);
struct acpi_device *acpi_fetch_acpi_dev(acpi_handle handle);
acpi_status acpi_bus_get_status_handle(acpi_handle handle, acpi_status acpi_bus_get_status_handle(acpi_handle handle,
unsigned long long *sta); unsigned long long *sta);
int acpi_bus_get_status(struct acpi_device *device); int acpi_bus_get_status(struct acpi_device *device);
...@@ -621,6 +622,22 @@ static inline bool acpi_device_always_present(struct acpi_device *adev) ...@@ -621,6 +622,22 @@ static inline bool acpi_device_always_present(struct acpi_device *adev)
} }
#endif #endif
#if IS_ENABLED(CONFIG_X86_ANDROID_TABLETS)
bool acpi_quirk_skip_i2c_client_enumeration(struct acpi_device *adev);
int acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *skip);
#else
static inline bool acpi_quirk_skip_i2c_client_enumeration(struct acpi_device *adev)
{
return false;
}
static inline int
acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *skip)
{
*skip = false;
return 0;
}
#endif
#ifdef CONFIG_PM #ifdef CONFIG_PM
void acpi_pm_wakeup_event(struct device *dev); void acpi_pm_wakeup_event(struct device *dev);
acpi_status acpi_add_pm_notifier(struct acpi_device *adev, struct device *dev, acpi_status acpi_add_pm_notifier(struct acpi_device *adev, struct device *dev,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment