Merge branches 'acpi-scan', 'acpi-bus' and 'acpi-platform'
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Fri, 30 Sep 2022 18:28:22 +0000 (20:28 +0200)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Fri, 30 Sep 2022 18:28:22 +0000 (20:28 +0200)
Merge changes related to ACPI device enumeration and ACPI support for
platform devices for 6.1-rc1:

 - Clean up ACPI platform devices support code (Andy Shevchenko, John
   Garry).

 - Clean up ACPI bus management code (Andy Shevchenko, ye xingchen).

 - Add support for multiple DMA windows with different offsets to the
   ACPI device enumeration code and use it on LoongArch (Jianmin Lv).

* acpi-scan:
  LoongArch: Use acpi_arch_dma_setup() and remove ARCH_HAS_PHYS_TO_DMA
  ACPI: scan: Support multiple DMA windows with different offsets

* acpi-bus:
  ACPI: bus: Refactor ACPI matching functions for better readability
  ACPI: bus: Drop kernel doc annotation from acpi_bus_notify()
  ACPI: bus: Remove the unneeded result variable

* acpi-platform:
  ACPI: platform: Use PLATFORM_DEVID_NONE in acpi_create_platform_device()
  ACPI: platform: Sort forbidden_id_list[] in ascending order
  ACPI: platform: Use sizeof(*pointer) instead of sizeof(type)
  ACPI: platform: Remove redundant print on -ENOMEM
  ACPI: platform: Get rid of redundant 'else'

32 files changed:
drivers/acpi/acpi_amba.c
drivers/acpi/acpi_apd.c
drivers/acpi/acpi_lpss.c
drivers/acpi/acpi_platform.c
drivers/acpi/acpi_video.c
drivers/acpi/bus.c
drivers/acpi/device_pm.c
drivers/acpi/internal.h
drivers/acpi/irq.c
drivers/acpi/pci_root.c
drivers/acpi/power.c
drivers/acpi/property.c
drivers/acpi/resource.c
drivers/acpi/sbs.c
drivers/acpi/sbshc.c
drivers/acpi/scan.c
drivers/acpi/x86/s2idle.c
drivers/clk/clk-tps68470.c
drivers/hv/vmbus_drv.c
drivers/hwmon/acpi_power_meter.c
drivers/perf/arm_dsu_pmu.c
drivers/perf/qcom_l3_pmu.c
drivers/platform/x86/intel/int3472/common.c
drivers/platform/x86/intel/int3472/tps68470.c
drivers/platform/x86/intel/int3472/tps68470.h
drivers/platform/x86/intel/int3472/tps68470_board_data.c
drivers/spi/spi.c
drivers/thunderbolt/acpi.c
drivers/usb/typec/mux/intel_pmc_mux.c
include/acpi/acpi_bus.h
include/linux/acpi.h
include/linux/platform_data/tps68470.h

index ab8a4e0..9d69546 100644 (file)
@@ -48,6 +48,7 @@ static void amba_register_dummy_clk(void)
 static int amba_handler_attach(struct acpi_device *adev,
                                const struct acpi_device_id *id)
 {
+       struct acpi_device *parent = acpi_dev_parent(adev);
        struct amba_device *dev;
        struct resource_entry *rentry;
        struct list_head resource_list;
@@ -97,8 +98,8 @@ static int amba_handler_attach(struct acpi_device *adev,
         * attached to it, that physical device should be the parent of
         * the amba device we are about to create.
         */
-       if (adev->parent)
-               dev->dev.parent = acpi_get_first_physical_node(adev->parent);
+       if (parent)
+               dev->dev.parent = acpi_get_first_physical_node(parent);
 
        ACPI_COMPANION_SET(&dev->dev, adev);
 
index ad245bb..3bbe227 100644 (file)
@@ -60,12 +60,6 @@ static int acpi_apd_setup(struct apd_private_data *pdata)
 }
 
 #ifdef CONFIG_X86_AMD_PLATFORM_DEVICE
-static int misc_check_res(struct acpi_resource *ares, void *data)
-{
-       struct resource res;
-
-       return !acpi_dev_resource_memory(ares, &res);
-}
 
 static int fch_misc_setup(struct apd_private_data *pdata)
 {
@@ -82,8 +76,7 @@ static int fch_misc_setup(struct apd_private_data *pdata)
                return -ENOMEM;
 
        INIT_LIST_HEAD(&resource_list);
-       ret = acpi_dev_get_resources(adev, &resource_list, misc_check_res,
-                                    NULL);
+       ret = acpi_dev_get_memory_resources(adev, &resource_list);
        if (ret < 0)
                return -ENOENT;
 
index c4d4d21..4f6cba8 100644 (file)
@@ -392,13 +392,6 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = {
 
 #ifdef CONFIG_X86_INTEL_LPSS
 
-static int is_memory(struct acpi_resource *res, void *not_used)
-{
-       struct resource r;
-
-       return !acpi_dev_resource_memory(res, &r);
-}
-
 /* LPSS main clock device. */
 static struct platform_device *lpss_clk_dev;
 
@@ -659,7 +652,7 @@ static int acpi_lpss_create_device(struct acpi_device *adev,
                return -ENOMEM;
 
        INIT_LIST_HEAD(&resource_list);
-       ret = acpi_dev_get_resources(adev, &resource_list, is_memory, NULL);
+       ret = acpi_dev_get_memory_resources(adev, &resource_list);
        if (ret < 0)
                goto err_out;
 
index de3cbf1..fe00a57 100644 (file)
 #include "internal.h"
 
 static const struct acpi_device_id forbidden_id_list[] = {
+       {"ACPI0009", 0},        /* IOxAPIC */
+       {"ACPI000A", 0},        /* IOAPIC */
        {"PNP0000",  0},        /* PIC */
        {"PNP0100",  0},        /* Timer */
        {"PNP0200",  0},        /* AT DMA Controller */
-       {"ACPI0009", 0},        /* IOxAPIC */
-       {"ACPI000A", 0},        /* IOAPIC */
        {"SMB0001",  0},        /* ACPI SMBUS virtual device */
-       {"", 0},
+       { }
 };
 
 static struct platform_device *acpi_platform_device_find_by_companion(struct acpi_device *adev)
@@ -78,7 +78,7 @@ static void acpi_platform_fill_resource(struct acpi_device *adev,
         * If the device has parent we need to take its resources into
         * account as well because this device might consume part of those.
         */
-       parent = acpi_get_first_physical_node(adev->parent);
+       parent = acpi_get_first_physical_node(acpi_dev_parent(adev));
        if (parent && dev_is_pci(parent))
                dest->parent = pci_find_resource(to_pci_dev(parent), dest);
 }
@@ -97,6 +97,7 @@ static void acpi_platform_fill_resource(struct acpi_device *adev,
 struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
                                                    const struct property_entry *properties)
 {
+       struct acpi_device *parent = acpi_dev_parent(adev);
        struct platform_device *pdev = NULL;
        struct platform_device_info pdevinfo;
        struct resource_entry *rentry;
@@ -113,13 +114,11 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
 
        INIT_LIST_HEAD(&resource_list);
        count = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
-       if (count < 0) {
+       if (count < 0)
                return NULL;
-       } else if (count > 0) {
-               resources = kcalloc(count, sizeof(struct resource),
-                                   GFP_KERNEL);
+       if (count > 0) {
+               resources = kcalloc(count, sizeof(*resources), GFP_KERNEL);
                if (!resources) {
-                       dev_err(&adev->dev, "No memory for resources\n");
                        acpi_dev_free_resource_list(&resource_list);
                        return ERR_PTR(-ENOMEM);
                }
@@ -137,10 +136,9 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
         * attached to it, that physical device should be the parent of the
         * platform device we are about to create.
         */
-       pdevinfo.parent = adev->parent ?
-               acpi_get_first_physical_node(adev->parent) : NULL;
+       pdevinfo.parent = parent ? acpi_get_first_physical_node(parent) : NULL;
        pdevinfo.name = dev_name(&adev->dev);
-       pdevinfo.id = -1;
+       pdevinfo.id = PLATFORM_DEVID_NONE;
        pdevinfo.res = resources;
        pdevinfo.num_res = count;
        pdevinfo.fwnode = acpi_fwnode_handle(adev);
index 5cbe219..92a6c6f 100644 (file)
@@ -2030,7 +2030,7 @@ static int acpi_video_bus_add(struct acpi_device *device)
        acpi_status status;
 
        status = acpi_walk_namespace(ACPI_TYPE_DEVICE,
-                               device->parent->handle, 1,
+                               acpi_dev_parent(device)->handle, 1,
                                acpi_video_bus_match, NULL,
                                device, NULL);
        if (status == AE_ALREADY_EXISTS) {
index c0d20d9..45eb901 100644 (file)
@@ -456,7 +456,7 @@ out_free:
                              Notification Handling
    -------------------------------------------------------------------------- */
 
-/**
+/*
  * acpi_bus_notify
  * ---------------
  * Callback for all 'system-level' device notifications (values 0x00-0x7F).
@@ -511,7 +511,7 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data)
                break;
        }
 
-       adev = acpi_bus_get_acpi_device(handle);
+       adev = acpi_get_acpi_dev(handle);
        if (!adev)
                goto err;
 
@@ -524,14 +524,14 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data)
        }
 
        if (!hotplug_event) {
-               acpi_bus_put_acpi_device(adev);
+               acpi_put_acpi_dev(adev);
                return;
        }
 
        if (ACPI_SUCCESS(acpi_hotplug_schedule(adev, type)))
                return;
 
-       acpi_bus_put_acpi_device(adev);
+       acpi_put_acpi_dev(adev);
 
  err:
        acpi_evaluate_ost(handle, type, ost_code, NULL);
@@ -925,12 +925,13 @@ static const void *acpi_of_device_get_match_data(const struct device *dev)
 
 const void *acpi_device_get_match_data(const struct device *dev)
 {
+       const struct acpi_device_id *acpi_ids = dev->driver->acpi_match_table;
        const struct acpi_device_id *match;
 
-       if (!dev->driver->acpi_match_table)
+       if (!acpi_ids)
                return acpi_of_device_get_match_data(dev);
 
-       match = acpi_match_device(dev->driver->acpi_match_table, dev);
+       match = acpi_match_device(acpi_ids, dev);
        if (!match)
                return NULL;
 
@@ -948,14 +949,13 @@ EXPORT_SYMBOL(acpi_match_device_ids);
 bool acpi_driver_match_device(struct device *dev,
                              const struct device_driver *drv)
 {
-       if (!drv->acpi_match_table)
-               return acpi_of_match_device(ACPI_COMPANION(dev),
-                                           drv->of_match_table,
-                                           NULL);
-
-       return __acpi_match_device(acpi_companion_match(dev),
-                                  drv->acpi_match_table, drv->of_match_table,
-                                  NULL, NULL);
+       const struct acpi_device_id *acpi_ids = drv->acpi_match_table;
+       const struct of_device_id *of_ids = drv->of_match_table;
+
+       if (!acpi_ids)
+               return acpi_of_match_device(ACPI_COMPANION(dev), of_ids, NULL);
+
+       return __acpi_match_device(acpi_companion_match(dev), acpi_ids, of_ids, NULL, NULL);
 }
 EXPORT_SYMBOL_GPL(acpi_driver_match_device);
 
@@ -973,16 +973,13 @@ EXPORT_SYMBOL_GPL(acpi_driver_match_device);
  */
 int acpi_bus_register_driver(struct acpi_driver *driver)
 {
-       int ret;
-
        if (acpi_disabled)
                return -ENODEV;
        driver->drv.name = driver->name;
        driver->drv.bus = &acpi_bus_type;
        driver->drv.owner = driver->owner;
 
-       ret = driver_register(&driver->drv);
-       return ret;
+       return driver_register(&driver->drv);
 }
 
 EXPORT_SYMBOL(acpi_bus_register_driver);
index 9dce124..d594eff 100644 (file)
@@ -75,15 +75,17 @@ static int acpi_dev_pm_explicit_get(struct acpi_device *device, int *state)
 int acpi_device_get_power(struct acpi_device *device, int *state)
 {
        int result = ACPI_STATE_UNKNOWN;
+       struct acpi_device *parent;
        int error;
 
        if (!device || !state)
                return -EINVAL;
 
+       parent = acpi_dev_parent(device);
+
        if (!device->flags.power_manageable) {
                /* TBD: Non-recursive algorithm for walking up hierarchy. */
-               *state = device->parent ?
-                       device->parent->power.state : ACPI_STATE_D0;
+               *state = parent ? parent->power.state : ACPI_STATE_D0;
                goto out;
        }
 
@@ -122,10 +124,10 @@ int acpi_device_get_power(struct acpi_device *device, int *state)
         * point, the fact that the device is in D0 implies that the parent has
         * to be in D0 too, except if ignore_parent is set.
         */
-       if (!device->power.flags.ignore_parent && device->parent
-           && device->parent->power.state == ACPI_STATE_UNKNOWN
-           && result == ACPI_STATE_D0)
-               device->parent->power.state = ACPI_STATE_D0;
+       if (!device->power.flags.ignore_parent && parent &&
+           parent->power.state == ACPI_STATE_UNKNOWN &&
+           result == ACPI_STATE_D0)
+               parent->power.state = ACPI_STATE_D0;
 
        *state = result;
 
@@ -191,13 +193,17 @@ int acpi_device_set_power(struct acpi_device *device, int state)
                return -ENODEV;
        }
 
-       if (!device->power.flags.ignore_parent && device->parent &&
-           state < device->parent->power.state) {
-               acpi_handle_debug(device->handle,
-                                 "Cannot transition to %s for parent in %s\n",
-                                 acpi_power_state_string(state),
-                                 acpi_power_state_string(device->parent->power.state));
-               return -ENODEV;
+       if (!device->power.flags.ignore_parent) {
+               struct acpi_device *parent;
+
+               parent = acpi_dev_parent(device);
+               if (parent && state < parent->power.state) {
+                       acpi_handle_debug(device->handle,
+                                         "Cannot transition to %s for parent in %s\n",
+                                         acpi_power_state_string(state),
+                                         acpi_power_state_string(parent->power.state));
+                       return -ENODEV;
+               }
        }
 
        /*
@@ -497,7 +503,7 @@ static void acpi_pm_notify_handler(acpi_handle handle, u32 val, void *not_used)
 
        acpi_handle_debug(handle, "Wake notify\n");
 
-       adev = acpi_bus_get_acpi_device(handle);
+       adev = acpi_get_acpi_dev(handle);
        if (!adev)
                return;
 
@@ -515,7 +521,7 @@ static void acpi_pm_notify_handler(acpi_handle handle, u32 val, void *not_used)
 
        mutex_unlock(&acpi_pm_notifier_lock);
 
-       acpi_bus_put_acpi_device(adev);
+       acpi_put_acpi_dev(adev);
 }
 
 /**
@@ -1460,7 +1466,7 @@ EXPORT_SYMBOL_GPL(acpi_storage_d3);
  * not valid to ask for the ACPI power state of the device in that time frame.
  *
  * This function is intended to be used in a driver's probe or remove
- * function. See Documentation/firmware-guide/acpi/low-power-probe.rst for
+ * function. See Documentation/firmware-guide/acpi/non-d0-probe.rst for
  * more information.
  */
 bool acpi_dev_state_d0(struct device *dev)
index 628bf8f..219c02d 100644 (file)
@@ -102,10 +102,10 @@ struct acpi_device_bus_id {
        struct list_head node;
 };
 
-int acpi_device_add(struct acpi_device *device,
-                   void (*release)(struct device *));
 void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
-                            int type);
+                            int type, void (*release)(struct device *));
+int acpi_tie_acpi_dev(struct acpi_device *adev);
+int acpi_device_add(struct acpi_device *device);
 int acpi_device_setup_files(struct acpi_device *dev);
 void acpi_device_remove_files(struct acpi_device *dev);
 void acpi_device_add_finalize(struct acpi_device *device);
index dabe45e..4db5bb5 100644 (file)
@@ -118,12 +118,12 @@ acpi_get_irq_source_fwhandle(const struct acpi_resource_source *source,
        if (WARN_ON(ACPI_FAILURE(status)))
                return NULL;
 
-       device = acpi_bus_get_acpi_device(handle);
+       device = acpi_get_acpi_dev(handle);
        if (WARN_ON(!device))
                return NULL;
 
        result = &device->fwnode;
-       acpi_bus_put_acpi_device(device);
+       acpi_put_acpi_dev(device);
        return result;
 }
 
index d57cf84..c8385ef 100644 (file)
@@ -312,76 +312,25 @@ struct acpi_handle_node {
  */
 struct pci_dev *acpi_get_pci_dev(acpi_handle handle)
 {
-       int dev, fn;
-       unsigned long long adr;
-       acpi_status status;
-       acpi_handle phandle;
-       struct pci_bus *pbus;
-       struct pci_dev *pdev = NULL;
-       struct acpi_handle_node *node, *tmp;
-       struct acpi_pci_root *root;
-       LIST_HEAD(device_list);
-
-       /*
-        * Walk up the ACPI CA namespace until we reach a PCI root bridge.
-        */
-       phandle = handle;
-       while (!acpi_is_root_bridge(phandle)) {
-               node = kzalloc(sizeof(struct acpi_handle_node), GFP_KERNEL);
-               if (!node)
-                       goto out;
-
-               INIT_LIST_HEAD(&node->node);
-               node->handle = phandle;
-               list_add(&node->node, &device_list);
-
-               status = acpi_get_parent(phandle, &phandle);
-               if (ACPI_FAILURE(status))
-                       goto out;
-       }
-
-       root = acpi_pci_find_root(phandle);
-       if (!root)
-               goto out;
+       struct acpi_device *adev = acpi_fetch_acpi_dev(handle);
+       struct acpi_device_physical_node *pn;
+       struct pci_dev *pci_dev = NULL;
 
-       pbus = root->bus;
-
-       /*
-        * Now, walk back down the PCI device tree until we return to our
-        * original handle. Assumes that everything between the PCI root
-        * bridge and the device we're looking for must be a P2P bridge.
-        */
-       list_for_each_entry(node, &device_list, node) {
-               acpi_handle hnd = node->handle;
-               status = acpi_evaluate_integer(hnd, "_ADR", NULL, &adr);
-               if (ACPI_FAILURE(status))
-                       goto out;
-               dev = (adr >> 16) & 0xffff;
-               fn  = adr & 0xffff;
-
-               pdev = pci_get_slot(pbus, PCI_DEVFN(dev, fn));
-               if (!pdev || hnd == handle)
-                       break;
+       if (!adev)
+               return NULL;
 
-               pbus = pdev->subordinate;
-               pci_dev_put(pdev);
+       mutex_lock(&adev->physical_node_lock);
 
-               /*
-                * This function may be called for a non-PCI device that has a
-                * PCI parent (eg. a disk under a PCI SATA controller).  In that
-                * case pdev->subordinate will be NULL for the parent.
-                */
-               if (!pbus) {
-                       dev_dbg(&pdev->dev, "Not a PCI-to-PCI bridge\n");
-                       pdev = NULL;
+       list_for_each_entry(pn, &adev->physical_node_list, node) {
+               if (dev_is_pci(pn->dev)) {
+                       pci_dev = to_pci_dev(pn->dev);
                        break;
                }
        }
-out:
-       list_for_each_entry_safe(node, tmp, &device_list, node)
-               kfree(node);
 
-       return pdev;
+       mutex_unlock(&adev->physical_node_lock);
+
+       return pci_dev;
 }
 EXPORT_SYMBOL_GPL(acpi_get_pci_dev);
 
index 8c4a73a..f2588ab 100644 (file)
@@ -944,13 +944,15 @@ struct acpi_device *acpi_add_power_resource(acpi_handle handle)
                return NULL;
 
        device = &resource->device;
-       acpi_init_device_object(device, handle, ACPI_BUS_TYPE_POWER);
+       acpi_init_device_object(device, handle, ACPI_BUS_TYPE_POWER,
+                               acpi_release_power_resource);
        mutex_init(&resource->resource_lock);
        INIT_LIST_HEAD(&resource->list_node);
        INIT_LIST_HEAD(&resource->dependents);
        strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME);
        strcpy(acpi_device_class(device), ACPI_POWER_CLASS);
        device->power.state = ACPI_STATE_UNKNOWN;
+       device->flags.match_driver = true;
 
        /* Evaluate the object to get the system level and resource order. */
        status = acpi_evaluate_object(handle, NULL, NULL, &buffer);
@@ -967,8 +969,11 @@ struct acpi_device *acpi_add_power_resource(acpi_handle handle)
 
        pr_info("%s [%s]\n", acpi_device_name(device), acpi_device_bid(device));
 
-       device->flags.match_driver = true;
-       result = acpi_device_add(device, acpi_release_power_resource);
+       result = acpi_tie_acpi_dev(device);
+       if (result)
+               goto err;
+
+       result = acpi_device_add(device);
        if (result)
                goto err;
 
index d4c168c..b8d9eb9 100644 (file)
@@ -304,8 +304,10 @@ static void acpi_init_of_compatible(struct acpi_device *adev)
                ret = acpi_dev_get_property(adev, "compatible",
                                            ACPI_TYPE_STRING, &of_compatible);
                if (ret) {
-                       if (adev->parent
-                           && adev->parent->flags.of_compatible_ok)
+                       struct acpi_device *parent;
+
+                       parent = acpi_dev_parent(adev);
+                       if (parent && parent->flags.of_compatible_ok)
                                goto out;
 
                        return;
@@ -1267,10 +1269,11 @@ acpi_node_get_parent(const struct fwnode_handle *fwnode)
                return to_acpi_data_node(fwnode)->parent;
        }
        if (is_acpi_device_node(fwnode)) {
-               struct device *dev = to_acpi_device_node(fwnode)->dev.parent;
+               struct acpi_device *parent;
 
-               if (dev)
-                       return acpi_fwnode_handle(to_acpi_device(dev));
+               parent = acpi_dev_parent(to_acpi_device_node(fwnode));
+               if (parent)
+                       return acpi_fwnode_handle(parent);
        }
 
        return NULL;
index 510cdec..514d896 100644 (file)
@@ -399,6 +399,31 @@ static const struct dmi_system_id medion_laptop[] = {
        { }
 };
 
+static const struct dmi_system_id asus_laptop[] = {
+       {
+               .ident = "Asus Vivobook K3402ZA",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+                       DMI_MATCH(DMI_BOARD_NAME, "K3402ZA"),
+               },
+       },
+       {
+               .ident = "Asus Vivobook K3502ZA",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+                       DMI_MATCH(DMI_BOARD_NAME, "K3502ZA"),
+               },
+       },
+       {
+               .ident = "Asus Vivobook S5402ZA",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+                       DMI_MATCH(DMI_BOARD_NAME, "S5402ZA"),
+               },
+       },
+       { }
+};
+
 struct irq_override_cmp {
        const struct dmi_system_id *system;
        unsigned char irq;
@@ -409,6 +434,7 @@ struct irq_override_cmp {
 
 static const struct irq_override_cmp skip_override_table[] = {
        { medion_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0 },
+       { asus_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0 },
 };
 
 static bool acpi_dev_irq_override(u32 gsi, u8 triggering, u8 polarity,
@@ -690,6 +716,9 @@ static int is_memory(struct acpi_resource *ares, void *not_used)
 
        memset(&win, 0, sizeof(win));
 
+       if (acpi_dev_filter_resource_type(ares, IORESOURCE_MEM))
+               return 1;
+
        return !(acpi_dev_resource_memory(ares, res)
               || acpi_dev_resource_address_space(ares, &win)
               || acpi_dev_resource_ext_address_space(ares, &win));
@@ -719,6 +748,23 @@ int acpi_dev_get_dma_resources(struct acpi_device *adev, struct list_head *list)
 EXPORT_SYMBOL_GPL(acpi_dev_get_dma_resources);
 
 /**
+ * acpi_dev_get_memory_resources - Get current memory resources of a device.
+ * @adev: ACPI device node to get the resources for.
+ * @list: Head of the resultant list of resources (must be empty).
+ *
+ * This is a helper function that locates all memory type resources of @adev
+ * with acpi_dev_get_resources().
+ *
+ * The number of resources in the output list is returned on success, an error
+ * code reflecting the error condition is returned otherwise.
+ */
+int acpi_dev_get_memory_resources(struct acpi_device *adev, struct list_head *list)
+{
+       return acpi_dev_get_resources(adev, list, is_memory, NULL);
+}
+EXPORT_SYMBOL_GPL(acpi_dev_get_memory_resources);
+
+/**
  * acpi_dev_filter_resource_type - Filter ACPI resource according to resource
  *                                types
  * @ares: Input ACPI resource object.
index 4938010..e6a01a8 100644 (file)
@@ -632,7 +632,7 @@ static int acpi_sbs_add(struct acpi_device *device)
 
        mutex_init(&sbs->lock);
 
-       sbs->hc = acpi_driver_data(device->parent);
+       sbs->hc = acpi_driver_data(acpi_dev_parent(device));
        sbs->device = device;
        strcpy(acpi_device_name(device), ACPI_SBS_DEVICE_NAME);
        strcpy(acpi_device_class(device), ACPI_SBS_CLASS);
index 7c62e14..340e0b6 100644 (file)
@@ -266,7 +266,7 @@ static int acpi_smbus_hc_add(struct acpi_device *device)
        mutex_init(&hc->lock);
        init_waitqueue_head(&hc->wait);
 
-       hc->ec = acpi_driver_data(device->parent);
+       hc->ec = acpi_driver_data(acpi_dev_parent(device));
        hc->offset = (val >> 8) & 0xff;
        hc->query_bit = val & 0xff;
        device->driver_data = hc;
index f96ef85..558664d 100644 (file)
@@ -30,8 +30,6 @@ extern struct acpi_device *acpi_root;
 #define ACPI_BUS_HID                   "LNXSYBUS"
 #define ACPI_BUS_DEVICE_NAME           "System Bus"
 
-#define ACPI_IS_ROOT_DEVICE(device)    (!(device)->parent)
-
 #define INVALID_ACPI_HANDLE    ((acpi_handle)empty_zero_page)
 
 static const char *dummy_hid = "device";
@@ -430,7 +428,7 @@ void acpi_device_hotplug(struct acpi_device *adev, u32 src)
        acpi_evaluate_ost(adev->handle, src, ost_code, NULL);
 
  out:
-       acpi_bus_put_acpi_device(adev);
+       acpi_put_acpi_dev(adev);
        mutex_unlock(&acpi_scan_lock);
        unlock_device_hotplug();
 }
@@ -600,11 +598,22 @@ static void get_acpi_device(void *dev)
        acpi_dev_get(dev);
 }
 
-struct acpi_device *acpi_bus_get_acpi_device(acpi_handle handle)
+/**
+ * acpi_get_acpi_dev - Retrieve ACPI device object and reference count it.
+ * @handle: ACPI handle associated with the requested ACPI device object.
+ *
+ * Return a pointer to the ACPI device object associated with @handle and bump
+ * up that object's reference counter (under the ACPI Namespace lock), if
+ * present, or return NULL otherwise.
+ *
+ * The ACPI device object reference acquired by this function needs to be
+ * dropped via acpi_dev_put().
+ */
+struct acpi_device *acpi_get_acpi_dev(acpi_handle handle)
 {
        return handle_to_device(handle, get_acpi_device);
 }
-EXPORT_SYMBOL_GPL(acpi_bus_get_acpi_device);
+EXPORT_SYMBOL_GPL(acpi_get_acpi_dev);
 
 static struct acpi_device_bus_id *acpi_device_bus_id_match(const char *dev_id)
 {
@@ -633,7 +642,7 @@ static int acpi_device_set_name(struct acpi_device *device,
        return 0;
 }
 
-static int acpi_tie_acpi_dev(struct acpi_device *adev)
+int acpi_tie_acpi_dev(struct acpi_device *adev)
 {
        acpi_handle handle = adev->handle;
        acpi_status status;
@@ -663,8 +672,7 @@ static void acpi_store_pld_crc(struct acpi_device *adev)
        ACPI_FREE(pld);
 }
 
-static int __acpi_device_add(struct acpi_device *device,
-                            void (*release)(struct device *))
+int acpi_device_add(struct acpi_device *device)
 {
        struct acpi_device_bus_id *acpi_device_bus_id;
        int result;
@@ -720,11 +728,6 @@ static int __acpi_device_add(struct acpi_device *device,
 
        mutex_unlock(&acpi_device_lock);
 
-       if (device->parent)
-               device->dev.parent = &device->parent->dev;
-
-       device->dev.bus = &acpi_bus_type;
-       device->dev.release = release;
        result = device_add(&device->dev);
        if (result) {
                dev_err(&device->dev, "Error registering device\n");
@@ -751,17 +754,6 @@ err_unlock:
        return result;
 }
 
-int acpi_device_add(struct acpi_device *adev, void (*release)(struct device *))
-{
-       int ret;
-
-       ret = acpi_tie_acpi_dev(adev);
-       if (ret)
-               return ret;
-
-       return __acpi_device_add(adev, release);
-}
-
 /* --------------------------------------------------------------------------
                                  Device Enumeration
    -------------------------------------------------------------------------- */
@@ -806,10 +798,9 @@ static const char * const acpi_honor_dep_ids[] = {
        NULL
 };
 
-static struct acpi_device *acpi_bus_get_parent(acpi_handle handle)
+static struct acpi_device *acpi_find_parent_acpi_dev(acpi_handle handle)
 {
-       struct acpi_device *device;
-       acpi_status status;
+       struct acpi_device *adev;
 
        /*
         * Fixed hardware devices do not appear in the namespace and do not
@@ -820,13 +811,18 @@ static struct acpi_device *acpi_bus_get_parent(acpi_handle handle)
                return acpi_root;
 
        do {
+               acpi_status status;
+
                status = acpi_get_parent(handle, &handle);
-               if (ACPI_FAILURE(status))
-                       return status == AE_NULL_ENTRY ? NULL : acpi_root;
+               if (ACPI_FAILURE(status)) {
+                       if (status != AE_NULL_ENTRY)
+                               return acpi_root;
 
-               device = acpi_fetch_acpi_dev(handle);
-       } while (!device);
-       return device;
+                       return NULL;
+               }
+               adev = acpi_fetch_acpi_dev(handle);
+       } while (!adev);
+       return adev;
 }
 
 acpi_status
@@ -1113,7 +1109,7 @@ static void acpi_device_get_busid(struct acpi_device *device)
         * The device's Bus ID is simply the object name.
         * TBD: Shouldn't this value be unique (within the ACPI namespace)?
         */
-       if (ACPI_IS_ROOT_DEVICE(device)) {
+       if (!acpi_dev_parent(device)) {
                strcpy(device->pnp.bus_id, "ACPI");
                return;
        }
@@ -1641,7 +1637,7 @@ static void acpi_init_coherency(struct acpi_device *adev)
 {
        unsigned long long cca = 0;
        acpi_status status;
-       struct acpi_device *parent = adev->parent;
+       struct acpi_device *parent = acpi_dev_parent(adev);
 
        if (parent && parent->flags.cca_seen) {
                /*
@@ -1685,7 +1681,7 @@ static int acpi_check_serial_bus_slave(struct acpi_resource *ares, void *data)
 
 static bool acpi_is_indirect_io_slave(struct acpi_device *device)
 {
-       struct acpi_device *parent = device->parent;
+       struct acpi_device *parent = acpi_dev_parent(device);
        static const struct acpi_device_id indirect_io_hosts[] = {
                {"HISI0191", 0},
                {}
@@ -1755,12 +1751,16 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device)
 }
 
 void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
-                            int type)
+                            int type, void (*release)(struct device *))
 {
+       struct acpi_device *parent = acpi_find_parent_acpi_dev(handle);
+
        INIT_LIST_HEAD(&device->pnp.ids);
        device->device_type = type;
        device->handle = handle;
-       device->parent = acpi_bus_get_parent(handle);
+       device->dev.parent = parent ? &parent->dev : NULL;
+       device->dev.release = release;
+       device->dev.bus = &acpi_bus_type;
        fwnode_init(&device->fwnode, &acpi_device_fwnode_ops);
        acpi_set_device_status(device, ACPI_STA_DEFAULT);
        acpi_device_get_busid(device);
@@ -1814,7 +1814,7 @@ static int acpi_add_single_object(struct acpi_device **child,
        if (!device)
                return -ENOMEM;
 
-       acpi_init_device_object(device, handle, type);
+       acpi_init_device_object(device, handle, type, acpi_device_release);
        /*
         * Getting the status is delayed till here so that we can call
         * acpi_bus_get_status() and use its quirk handling.  Note that
@@ -1844,7 +1844,7 @@ static int acpi_add_single_object(struct acpi_device **child,
                mutex_unlock(&acpi_dep_list_lock);
 
        if (!result)
-               result = __acpi_device_add(device, acpi_device_release);
+               result = acpi_device_add(device);
 
        if (result) {
                acpi_device_release(&device->dev);
@@ -1855,8 +1855,8 @@ static int acpi_add_single_object(struct acpi_device **child,
        acpi_device_add_finalize(device);
 
        acpi_handle_debug(handle, "Added as %s, parent %s\n",
-                         dev_name(&device->dev), device->parent ?
-                               dev_name(&device->parent->dev) : "(null)");
+                         dev_name(&device->dev), device->dev.parent ?
+                               dev_name(device->dev.parent) : "(null)");
 
        *child = device;
        return 0;
@@ -2228,11 +2228,24 @@ ok:
        return 0;
 }
 
-static int acpi_dev_get_first_consumer_dev_cb(struct acpi_dep_data *dep, void *data)
+static int acpi_dev_get_next_consumer_dev_cb(struct acpi_dep_data *dep, void *data)
 {
-       struct acpi_device *adev;
+       struct acpi_device **adev_p = data;
+       struct acpi_device *adev = *adev_p;
+
+       /*
+        * If we're passed a 'previous' consumer device then we need to skip
+        * any consumers until we meet the previous one, and then NULL @data
+        * so the next one can be returned.
+        */
+       if (adev) {
+               if (dep->consumer == adev->handle)
+                       *adev_p = NULL;
+
+               return 0;
+       }
 
-       adev = acpi_bus_get_acpi_device(dep->consumer);
+       adev = acpi_get_acpi_dev(dep->consumer);
        if (adev) {
                *(struct acpi_device **)data = adev;
                return 1;
@@ -2285,7 +2298,7 @@ static bool acpi_scan_clear_dep_queue(struct acpi_device *adev)
 
 static int acpi_scan_clear_dep(struct acpi_dep_data *dep, void *data)
 {
-       struct acpi_device *adev = acpi_bus_get_acpi_device(dep->consumer);
+       struct acpi_device *adev = acpi_get_acpi_dev(dep->consumer);
 
        if (adev) {
                adev->dep_unmet--;
@@ -2361,25 +2374,32 @@ bool acpi_dev_ready_for_enumeration(const struct acpi_device *device)
 EXPORT_SYMBOL_GPL(acpi_dev_ready_for_enumeration);
 
 /**
- * acpi_dev_get_first_consumer_dev - Return ACPI device dependent on @supplier
+ * acpi_dev_get_next_consumer_dev - Return the next adev dependent on @supplier
  * @supplier: Pointer to the dependee device
+ * @start: Pointer to the current dependent device
  *
- * Returns the first &struct acpi_device which declares itself dependent on
+ * Returns the next &struct acpi_device which declares itself dependent on
  * @supplier via the _DEP buffer, parsed from the acpi_dep_list.
  *
- * The caller is responsible for putting the reference to adev when it is no
- * longer needed.
+ * If the returned adev is not passed as @start to this function, the caller is
+ * responsible for putting the reference to adev when it is no longer needed.
  */
-struct acpi_device *acpi_dev_get_first_consumer_dev(struct acpi_device *supplier)
+struct acpi_device *acpi_dev_get_next_consumer_dev(struct acpi_device *supplier,
+                                                  struct acpi_device *start)
 {
-       struct acpi_device *adev = NULL;
+       struct acpi_device *adev = start;
 
        acpi_walk_dep_device_list(supplier->handle,
-                                 acpi_dev_get_first_consumer_dev_cb, &adev);
+                                 acpi_dev_get_next_consumer_dev_cb, &adev);
+
+       acpi_dev_put(start);
+
+       if (adev == start)
+               return NULL;
 
        return adev;
 }
-EXPORT_SYMBOL_GPL(acpi_dev_get_first_consumer_dev);
+EXPORT_SYMBOL_GPL(acpi_dev_get_next_consumer_dev);
 
 /**
  * acpi_bus_scan - Add ACPI device node objects in a given namespace scope.
index f9ac12b..0155c1d 100644 (file)
@@ -17,6 +17,7 @@
 
 #include <linux/acpi.h>
 #include <linux/device.h>
+#include <linux/dmi.h>
 #include <linux/suspend.h>
 
 #include "../sleep.h"
@@ -27,6 +28,10 @@ static bool sleep_no_lps0 __read_mostly;
 module_param(sleep_no_lps0, bool, 0644);
 MODULE_PARM_DESC(sleep_no_lps0, "Do not use the special LPS0 device interface");
 
+static bool prefer_microsoft_dsm_guid __read_mostly;
+module_param(prefer_microsoft_dsm_guid, bool, 0644);
+MODULE_PARM_DESC(prefer_microsoft_dsm_guid, "Prefer using Microsoft GUID in LPS0 device _DSM evaluation");
+
 static const struct acpi_device_id lps0_device_ids[] = {
        {"PNP0D80", },
        {"", },
@@ -363,40 +368,132 @@ out:
        return ret;
 }
 
+struct amd_lps0_hid_device_data {
+       const unsigned int rev_id;
+       const bool check_off_by_one;
+       const bool prefer_amd_guid;
+};
+
+static const struct amd_lps0_hid_device_data amd_picasso = {
+       .rev_id = 0,
+       .check_off_by_one = true,
+       .prefer_amd_guid = false,
+};
+
+static const struct amd_lps0_hid_device_data amd_cezanne = {
+       .rev_id = 0,
+       .check_off_by_one = false,
+       .prefer_amd_guid = false,
+};
+
+static const struct amd_lps0_hid_device_data amd_rembrandt = {
+       .rev_id = 2,
+       .check_off_by_one = false,
+       .prefer_amd_guid = true,
+};
+
+static const struct acpi_device_id amd_hid_ids[] = {
+       {"AMD0004",     (kernel_ulong_t)&amd_picasso,   },
+       {"AMD0005",     (kernel_ulong_t)&amd_picasso,   },
+       {"AMDI0005",    (kernel_ulong_t)&amd_picasso,   },
+       {"AMDI0006",    (kernel_ulong_t)&amd_cezanne,   },
+       {"AMDI0007",    (kernel_ulong_t)&amd_rembrandt, },
+       {}
+};
+
+static int lps0_prefer_microsoft(const struct dmi_system_id *id)
+{
+       pr_debug("Preferring Microsoft GUID.\n");
+       prefer_microsoft_dsm_guid = true;
+       return 0;
+}
+
+static const struct dmi_system_id s2idle_dmi_table[] __initconst = {
+       {
+               /*
+                * ASUS TUF Gaming A17 FA707RE
+                * https://bugzilla.kernel.org/show_bug.cgi?id=216101
+                */
+               .callback = lps0_prefer_microsoft,
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ASUS TUF Gaming A17"),
+               },
+       },
+       {
+               /* ASUS ROG Zephyrus G14 (2022) */
+               .callback = lps0_prefer_microsoft,
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ROG Zephyrus G14 GA402"),
+               },
+       },
+       {
+               /*
+                * Lenovo Yoga Slim 7 Pro X 14ARH7
+                * https://bugzilla.kernel.org/show_bug.cgi?id=216473 : 82V2
+                * https://bugzilla.kernel.org/show_bug.cgi?id=216438 : 82TL
+                */
+               .callback = lps0_prefer_microsoft,
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "82"),
+               },
+       },
+       {
+               /*
+                * ASUSTeK COMPUTER INC. ROG Flow X13 GV301RE_GV301RE
+                * https://gitlab.freedesktop.org/drm/amd/-/issues/2148
+                */
+               .callback = lps0_prefer_microsoft,
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ROG Flow X13 GV301"),
+               },
+       },
+       {
+               /*
+                * ASUSTeK COMPUTER INC. ROG Flow X16 GV601RW_GV601RW
+                * https://gitlab.freedesktop.org/drm/amd/-/issues/2148
+                */
+               .callback = lps0_prefer_microsoft,
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ROG Flow X16 GV601"),
+               },
+       },
+       {}
+};
+
 static int lps0_device_attach(struct acpi_device *adev,
                              const struct acpi_device_id *not_used)
 {
        if (lps0_device_handle)
                return 0;
 
+       lps0_dsm_func_mask_microsoft = validate_dsm(adev->handle,
+                                                   ACPI_LPS0_DSM_UUID_MICROSOFT, 0,
+                                                   &lps0_dsm_guid_microsoft);
        if (acpi_s2idle_vendor_amd()) {
-               /* AMD0004, AMD0005, AMDI0005:
-                * - Should use rev_id 0x0
-                * - function mask > 0x3: Should use AMD method, but has off by one bug
-                * - function mask = 0x3: Should use Microsoft method
-                * AMDI0006:
-                * - should use rev_id 0x0
-                * - function mask = 0x3: Should use Microsoft method
-                * AMDI0007:
-                * - Should use rev_id 0x2
-                * - Should only use AMD method
-                */
-               const char *hid = acpi_device_hid(adev);
-               rev_id = strcmp(hid, "AMDI0007") ? 0 : 2;
+               static const struct acpi_device_id *dev_id;
+               const struct amd_lps0_hid_device_data *data;
+
+               for (dev_id = &amd_hid_ids[0]; dev_id->id[0]; dev_id++)
+                       if (acpi_dev_hid_uid_match(adev, dev_id->id, NULL))
+                               break;
+               if (dev_id->id[0])
+                       data = (const struct amd_lps0_hid_device_data *) dev_id->driver_data;
+               else
+                       data = &amd_rembrandt;
+               rev_id = data->rev_id;
                lps0_dsm_func_mask = validate_dsm(adev->handle,
                                        ACPI_LPS0_DSM_UUID_AMD, rev_id, &lps0_dsm_guid);
-               lps0_dsm_func_mask_microsoft = validate_dsm(adev->handle,
-                                       ACPI_LPS0_DSM_UUID_MICROSOFT, 0,
-                                       &lps0_dsm_guid_microsoft);
-               if (lps0_dsm_func_mask > 0x3 && (!strcmp(hid, "AMD0004") ||
-                                                !strcmp(hid, "AMD0005") ||
-                                                !strcmp(hid, "AMDI0005"))) {
+               if (lps0_dsm_func_mask > 0x3 && data->check_off_by_one) {
                        lps0_dsm_func_mask = (lps0_dsm_func_mask << 1) | 0x1;
                        acpi_handle_debug(adev->handle, "_DSM UUID %s: Adjusted function mask: 0x%x\n",
                                          ACPI_LPS0_DSM_UUID_AMD, lps0_dsm_func_mask);
-               } else if (lps0_dsm_func_mask_microsoft > 0 &&
-                               (!strcmp(hid, "AMDI0007") ||
-                                !strcmp(hid, "AMDI0008"))) {
+               } else if (lps0_dsm_func_mask_microsoft > 0 && data->prefer_amd_guid &&
+                               !prefer_microsoft_dsm_guid) {
                        lps0_dsm_func_mask_microsoft = -EINVAL;
                        acpi_handle_debug(adev->handle, "_DSM Using AMD method\n");
                }
@@ -404,7 +501,8 @@ static int lps0_device_attach(struct acpi_device *adev,
                rev_id = 1;
                lps0_dsm_func_mask = validate_dsm(adev->handle,
                                        ACPI_LPS0_DSM_UUID, rev_id, &lps0_dsm_guid);
-               lps0_dsm_func_mask_microsoft = -EINVAL;
+               if (!prefer_microsoft_dsm_guid)
+                       lps0_dsm_func_mask_microsoft = -EINVAL;
        }
 
        if (lps0_dsm_func_mask < 0 && lps0_dsm_func_mask_microsoft < 0)
@@ -533,8 +631,9 @@ static const struct platform_s2idle_ops acpi_s2idle_ops_lps0 = {
        .end = acpi_s2idle_end,
 };
 
-void acpi_s2idle_setup(void)
+void __init acpi_s2idle_setup(void)
 {
+       dmi_check_system(s2idle_dmi_table);
        acpi_scan_add_handler(&lps0_handler);
        s2idle_set_ops(&acpi_s2idle_ops_lps0);
 }
index e5fbefd..38f44b5 100644 (file)
@@ -200,7 +200,9 @@ static int tps68470_clk_probe(struct platform_device *pdev)
                .flags = CLK_SET_RATE_GATE,
        };
        struct tps68470_clkdata *tps68470_clkdata;
+       struct tps68470_clk_consumer *consumer;
        int ret;
+       int i;
 
        tps68470_clkdata = devm_kzalloc(&pdev->dev, sizeof(*tps68470_clkdata),
                                        GFP_KERNEL);
@@ -223,10 +225,13 @@ static int tps68470_clk_probe(struct platform_device *pdev)
                return ret;
 
        if (pdata) {
-               ret = devm_clk_hw_register_clkdev(&pdev->dev,
-                                                 &tps68470_clkdata->clkout_hw,
-                                                 pdata->consumer_con_id,
-                                                 pdata->consumer_dev_name);
+               for (i = 0; i < pdata->n_consumers; i++) {
+                       consumer = &pdata->consumers[i];
+                       ret = devm_clk_hw_register_clkdev(&pdev->dev,
+                                                         &tps68470_clkdata->clkout_hw,
+                                                         consumer->consumer_con_id,
+                                                         consumer->consumer_dev_name);
+               }
        }
 
        return ret;
index 3c833ea..7b9f3fc 100644 (file)
@@ -2453,7 +2453,8 @@ static int vmbus_acpi_add(struct acpi_device *device)
         * Some ancestor of the vmbus acpi device (Gen1 or Gen2
         * firmware) is the VMOD that has the mmio ranges. Get that.
         */
-       for (ancestor = device->parent; ancestor; ancestor = ancestor->parent) {
+       for (ancestor = acpi_dev_parent(device); ancestor;
+            ancestor = acpi_dev_parent(ancestor)) {
                result = acpi_walk_resources(ancestor->handle, METHOD_NAME__CRS,
                                             vmbus_walk_resources, NULL);
 
index d2545a1..44e04c7 100644 (file)
@@ -598,7 +598,7 @@ static int read_domain_devices(struct acpi_power_meter_resource *resource)
                        continue;
 
                /* Create a symlink to domain objects */
-               obj = acpi_bus_get_acpi_device(element->reference.handle);
+               obj = acpi_get_acpi_dev(element->reference.handle);
                resource->domain_devices[i] = obj;
                if (!obj)
                        continue;
index a36698a..4a15c86 100644 (file)
@@ -639,6 +639,7 @@ static int dsu_pmu_dt_get_cpus(struct device *dev, cpumask_t *mask)
 static int dsu_pmu_acpi_get_cpus(struct device *dev, cpumask_t *mask)
 {
 #ifdef CONFIG_ACPI
+       struct acpi_device *parent_adev = acpi_dev_parent(ACPI_COMPANION(dev));
        int cpu;
 
        /*
@@ -653,8 +654,7 @@ static int dsu_pmu_acpi_get_cpus(struct device *dev, cpumask_t *mask)
                        continue;
 
                acpi_dev = ACPI_COMPANION(cpu_dev);
-               if (acpi_dev &&
-                       acpi_dev->parent == ACPI_COMPANION(dev)->parent)
+               if (acpi_dev && acpi_dev_parent(acpi_dev) == parent_adev)
                        cpumask_set_cpu(cpu, mask);
        }
 #endif
index 1ff2ff6..346311a 100644 (file)
@@ -742,7 +742,8 @@ static int qcom_l3_cache_pmu_probe(struct platform_device *pdev)
 
        l3pmu = devm_kzalloc(&pdev->dev, sizeof(*l3pmu), GFP_KERNEL);
        name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "l3cache_%s_%s",
-                     acpi_dev->parent->pnp.unique_id, acpi_dev->pnp.unique_id);
+                     acpi_dev_parent(acpi_dev)->pnp.unique_id,
+                     acpi_dev->pnp.unique_id);
        if (!l3pmu || !name)
                return -ENOMEM;
 
index 77cf058..9db2bb0 100644 (file)
@@ -62,7 +62,7 @@ int skl_int3472_get_sensor_adev_and_name(struct device *dev,
        struct acpi_device *sensor;
        int ret = 0;
 
-       sensor = acpi_dev_get_first_consumer_dev(adev);
+       sensor = acpi_dev_get_next_consumer_dev(adev, NULL);
        if (!sensor) {
                dev_err(dev, "INT3472 seems to have no dependents.\n");
                return -ENODEV;
index 22f61b4..49fc379 100644 (file)
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 /* Author: Dan Scally <djrscally@gmail.com> */
 
+#include <linux/acpi.h>
 #include <linux/i2c.h>
 #include <linux/kernel.h>
 #include <linux/mfd/core.h>
@@ -95,20 +96,65 @@ static int skl_int3472_tps68470_calc_type(struct acpi_device *adev)
        return DESIGNED_FOR_WINDOWS;
 }
 
+/*
+ * Return the size of the flexible array member, because we'll need that later
+ * on to pass .pdata_size to cells.
+ */
+static int
+skl_int3472_fill_clk_pdata(struct device *dev, struct tps68470_clk_platform_data **clk_pdata)
+{
+       struct acpi_device *adev = ACPI_COMPANION(dev);
+       struct acpi_device *consumer;
+       unsigned int n_consumers = 0;
+       const char *sensor_name;
+       unsigned int i = 0;
+
+       for_each_acpi_consumer_dev(adev, consumer)
+               n_consumers++;
+
+       if (!n_consumers) {
+               dev_err(dev, "INT3472 seems to have no dependents\n");
+               return -ENODEV;
+       }
+
+       *clk_pdata = devm_kzalloc(dev, struct_size(*clk_pdata, consumers, n_consumers),
+                                 GFP_KERNEL);
+       if (!*clk_pdata)
+               return -ENOMEM;
+
+       (*clk_pdata)->n_consumers = n_consumers;
+       i = 0;
+
+       for_each_acpi_consumer_dev(adev, consumer) {
+               sensor_name = devm_kasprintf(dev, GFP_KERNEL, I2C_DEV_NAME_FORMAT,
+                                            acpi_dev_name(consumer));
+               if (!sensor_name)
+                       return -ENOMEM;
+
+               (*clk_pdata)->consumers[i].consumer_dev_name = sensor_name;
+               i++;
+       }
+
+       acpi_dev_put(consumer);
+
+       return n_consumers;
+}
+
 static int skl_int3472_tps68470_probe(struct i2c_client *client)
 {
        struct acpi_device *adev = ACPI_COMPANION(&client->dev);
        const struct int3472_tps68470_board_data *board_data;
-       struct tps68470_clk_platform_data clk_pdata = {};
+       struct tps68470_clk_platform_data *clk_pdata;
        struct mfd_cell *cells;
        struct regmap *regmap;
+       int n_consumers;
        int device_type;
        int ret;
+       int i;
 
-       ret = skl_int3472_get_sensor_adev_and_name(&client->dev, NULL,
-                                                  &clk_pdata.consumer_dev_name);
-       if (ret)
-               return ret;
+       n_consumers = skl_int3472_fill_clk_pdata(&client->dev, &clk_pdata);
+       if (n_consumers < 0)
+               return n_consumers;
 
        regmap = devm_regmap_init_i2c(client, &tps68470_regmap_config);
        if (IS_ERR(regmap)) {
@@ -142,22 +188,25 @@ static int skl_int3472_tps68470_probe(struct i2c_client *client)
                 * the clk + regulators must be ready when this happens.
                 */
                cells[0].name = "tps68470-clk";
-               cells[0].platform_data = &clk_pdata;
-               cells[0].pdata_size = sizeof(clk_pdata);
+               cells[0].platform_data = clk_pdata;
+               cells[0].pdata_size = struct_size(clk_pdata, consumers, n_consumers);
                cells[1].name = "tps68470-regulator";
                cells[1].platform_data = (void *)board_data->tps68470_regulator_pdata;
                cells[1].pdata_size = sizeof(struct tps68470_regulator_platform_data);
                cells[2].name = "tps68470-gpio";
 
-               gpiod_add_lookup_table(board_data->tps68470_gpio_lookup_table);
+               for (i = 0; i < board_data->n_gpiod_lookups; i++)
+                       gpiod_add_lookup_table(board_data->tps68470_gpio_lookup_tables[i]);
 
                ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE,
                                           cells, TPS68470_WIN_MFD_CELL_COUNT,
                                           NULL, 0, NULL);
                kfree(cells);
 
-               if (ret)
-                       gpiod_remove_lookup_table(board_data->tps68470_gpio_lookup_table);
+               if (ret) {
+                       for (i = 0; i < board_data->n_gpiod_lookups; i++)
+                               gpiod_remove_lookup_table(board_data->tps68470_gpio_lookup_tables[i]);
+               }
 
                break;
        case DESIGNED_FOR_CHROMEOS:
@@ -181,10 +230,13 @@ static int skl_int3472_tps68470_probe(struct i2c_client *client)
 static int skl_int3472_tps68470_remove(struct i2c_client *client)
 {
        const struct int3472_tps68470_board_data *board_data;
+       int i;
 
        board_data = int3472_tps68470_get_board_data(dev_name(&client->dev));
-       if (board_data)
-               gpiod_remove_lookup_table(board_data->tps68470_gpio_lookup_table);
+       if (board_data) {
+               for (i = 0; i < board_data->n_gpiod_lookups; i++)
+                       gpiod_remove_lookup_table(board_data->tps68470_gpio_lookup_tables[i]);
+       }
 
        return 0;
 }
index cfd33eb..35915e7 100644 (file)
@@ -16,8 +16,9 @@ struct tps68470_regulator_platform_data;
 
 struct int3472_tps68470_board_data {
        const char *dev_name;
-       struct gpiod_lookup_table *tps68470_gpio_lookup_table;
        const struct tps68470_regulator_platform_data *tps68470_regulator_pdata;
+       unsigned int n_gpiod_lookups;
+       struct gpiod_lookup_table *tps68470_gpio_lookup_tables[];
 };
 
 const struct int3472_tps68470_board_data *int3472_tps68470_get_board_data(const char *dev_name);
index 525f09a..309eab9 100644 (file)
@@ -30,6 +30,15 @@ static struct regulator_consumer_supply int347a_vcm_consumer_supplies[] = {
 static struct regulator_consumer_supply int347a_vsio_consumer_supplies[] = {
        REGULATOR_SUPPLY("dovdd", "i2c-INT347A:00"),
        REGULATOR_SUPPLY("vsio", "i2c-INT347A:00-VCM"),
+       REGULATOR_SUPPLY("vddd", "i2c-INT347E:00"),
+};
+
+static struct regulator_consumer_supply int347a_aux1_consumer_supplies[] = {
+       REGULATOR_SUPPLY("vdda", "i2c-INT347E:00"),
+};
+
+static struct regulator_consumer_supply int347a_aux2_consumer_supplies[] = {
+       REGULATOR_SUPPLY("vdddo", "i2c-INT347E:00"),
 };
 
 static const struct regulator_init_data surface_go_tps68470_core_reg_init_data = {
@@ -86,6 +95,28 @@ static const struct regulator_init_data surface_go_tps68470_vsio_reg_init_data =
        .consumer_supplies = int347a_vsio_consumer_supplies,
 };
 
+static const struct regulator_init_data surface_go_tps68470_aux1_reg_init_data = {
+       .constraints = {
+               .min_uV = 2815200,
+               .max_uV = 2815200,
+               .apply_uV = 1,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+       },
+       .num_consumer_supplies = ARRAY_SIZE(int347a_aux1_consumer_supplies),
+       .consumer_supplies = int347a_aux1_consumer_supplies,
+};
+
+static const struct regulator_init_data surface_go_tps68470_aux2_reg_init_data = {
+       .constraints = {
+               .min_uV = 1800600,
+               .max_uV = 1800600,
+               .apply_uV = 1,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+       },
+       .num_consumer_supplies = ARRAY_SIZE(int347a_aux2_consumer_supplies),
+       .consumer_supplies = int347a_aux2_consumer_supplies,
+};
+
 static const struct tps68470_regulator_platform_data surface_go_tps68470_pdata = {
        .reg_init_data = {
                [TPS68470_CORE] = &surface_go_tps68470_core_reg_init_data,
@@ -93,10 +124,12 @@ static const struct tps68470_regulator_platform_data surface_go_tps68470_pdata =
                [TPS68470_VCM]  = &surface_go_tps68470_vcm_reg_init_data,
                [TPS68470_VIO] = &surface_go_tps68470_vio_reg_init_data,
                [TPS68470_VSIO] = &surface_go_tps68470_vsio_reg_init_data,
+               [TPS68470_AUX1] = &surface_go_tps68470_aux1_reg_init_data,
+               [TPS68470_AUX2] = &surface_go_tps68470_aux2_reg_init_data,
        },
 };
 
-static struct gpiod_lookup_table surface_go_tps68470_gpios = {
+static struct gpiod_lookup_table surface_go_int347a_gpios = {
        .dev_id = "i2c-INT347A:00",
        .table = {
                GPIO_LOOKUP("tps68470-gpio", 9, "reset", GPIO_ACTIVE_LOW),
@@ -105,16 +138,31 @@ static struct gpiod_lookup_table surface_go_tps68470_gpios = {
        }
 };
 
+static struct gpiod_lookup_table surface_go_int347e_gpios = {
+       .dev_id = "i2c-INT347E:00",
+       .table = {
+               GPIO_LOOKUP("tps68470-gpio", 5, "enable", GPIO_ACTIVE_HIGH),
+               { }
+       }
+};
+
 static const struct int3472_tps68470_board_data surface_go_tps68470_board_data = {
        .dev_name = "i2c-INT3472:05",
-       .tps68470_gpio_lookup_table = &surface_go_tps68470_gpios,
        .tps68470_regulator_pdata = &surface_go_tps68470_pdata,
+       .n_gpiod_lookups = 2,
+       .tps68470_gpio_lookup_tables = {
+               &surface_go_int347a_gpios,
+               &surface_go_int347e_gpios,
+       },
 };
 
 static const struct int3472_tps68470_board_data surface_go3_tps68470_board_data = {
        .dev_name = "i2c-INT3472:01",
-       .tps68470_gpio_lookup_table = &surface_go_tps68470_gpios,
        .tps68470_regulator_pdata = &surface_go_tps68470_pdata,
+       .n_gpiod_lookups = 1,
+       .tps68470_gpio_lookup_tables = {
+               &surface_go_int347a_gpios
+       },
 };
 
 static const struct dmi_system_id int3472_tps68470_board_data_table[] = {
index 32c01e6..30e82f9 100644 (file)
@@ -4374,7 +4374,7 @@ static int acpi_spi_notify(struct notifier_block *nb, unsigned long value,
 
        switch (value) {
        case ACPI_RECONFIG_DEVICE_ADD:
-               ctlr = acpi_spi_find_controller_by_adev(adev->parent);
+               ctlr = acpi_spi_find_controller_by_adev(acpi_dev_parent(adev));
                if (!ctlr)
                        break;
 
index b1f0dc8..7a8adf5 100644 (file)
@@ -42,7 +42,7 @@ static acpi_status tb_acpi_add_link(acpi_handle handle, u32 level, void *data,
         */
        dev = acpi_get_first_physical_node(adev);
        while (!dev) {
-               adev = adev->parent;
+               adev = acpi_dev_parent(adev);
                if (!adev)
                        break;
                dev = acpi_get_first_physical_node(adev);
index a8e273f..e1f4df7 100644 (file)
@@ -569,15 +569,6 @@ err_unregister_switch:
        return ret;
 }
 
-static int is_memory(struct acpi_resource *res, void *data)
-{
-       struct resource_win win = {};
-       struct resource *r = &win.res;
-
-       return !(acpi_dev_resource_memory(res, r) ||
-                acpi_dev_resource_address_space(res, &win));
-}
-
 /* IOM ACPI IDs and IOM_PORT_STATUS_OFFSET */
 static const struct acpi_device_id iom_acpi_ids[] = {
        /* TigerLake */
@@ -611,7 +602,7 @@ static int pmc_usb_probe_iom(struct pmc_usb *pmc)
                return -ENODEV;
 
        INIT_LIST_HEAD(&resource_list);
-       ret = acpi_dev_get_resources(adev, &resource_list, is_memory, NULL);
+       ret = acpi_dev_get_memory_resources(adev, &resource_list);
        if (ret < 0)
                return ret;
 
index 73ac4a1..3cd269d 100644 (file)
@@ -365,7 +365,6 @@ struct acpi_device {
        int device_type;
        acpi_handle handle;             /* no handle for fixed hardware */
        struct fwnode_handle fwnode;
-       struct acpi_device *parent;
        struct list_head wakeup_list;
        struct list_head del_list;
        struct acpi_device_status status;
@@ -458,6 +457,14 @@ static inline void *acpi_driver_data(struct acpi_device *d)
 #define to_acpi_device(d)      container_of(d, struct acpi_device, dev)
 #define to_acpi_driver(d)      container_of(d, struct acpi_driver, drv)
 
+static inline struct acpi_device *acpi_dev_parent(struct acpi_device *adev)
+{
+       if (adev->dev.parent)
+               return to_acpi_device(adev->dev.parent);
+
+       return NULL;
+}
+
 static inline void acpi_set_device_status(struct acpi_device *adev, u32 sta)
 {
        *((u32 *)&adev->status) = sta;
@@ -512,7 +519,6 @@ extern int unregister_acpi_notifier(struct notifier_block *);
  * External Functions
  */
 
-struct acpi_device *acpi_fetch_acpi_dev(acpi_handle handle);
 acpi_status acpi_bus_get_status_handle(acpi_handle handle,
                                       unsigned long long *sta);
 int acpi_bus_get_status(struct acpi_device *device);
@@ -735,7 +741,20 @@ bool acpi_dev_hid_uid_match(struct acpi_device *adev, const char *hid2, const ch
 
 void acpi_dev_clear_dependencies(struct acpi_device *supplier);
 bool acpi_dev_ready_for_enumeration(const struct acpi_device *device);
-struct acpi_device *acpi_dev_get_first_consumer_dev(struct acpi_device *supplier);
+struct acpi_device *acpi_dev_get_next_consumer_dev(struct acpi_device *supplier,
+                                                  struct acpi_device *start);
+
+/**
+ * for_each_acpi_consumer_dev - iterate over the consumer ACPI devices for a
+ *                             given supplier
+ * @supplier: Pointer to the supplier's ACPI device
+ * @consumer: Pointer to &struct acpi_device to hold the consumer, initially NULL
+ */
+#define for_each_acpi_consumer_dev(supplier, consumer)                 \
+       for (consumer = acpi_dev_get_next_consumer_dev(supplier, NULL); \
+            consumer;                                                  \
+            consumer = acpi_dev_get_next_consumer_dev(supplier, consumer))
+
 struct acpi_device *
 acpi_dev_get_next_match_dev(struct acpi_device *adev, const char *hid, const char *uid, s64 hrv);
 struct acpi_device *
@@ -766,9 +785,10 @@ static inline void acpi_dev_put(struct acpi_device *adev)
                put_device(&adev->dev);
 }
 
-struct acpi_device *acpi_bus_get_acpi_device(acpi_handle handle);
+struct acpi_device *acpi_fetch_acpi_dev(acpi_handle handle);
+struct acpi_device *acpi_get_acpi_dev(acpi_handle handle);
 
-static inline void acpi_bus_put_acpi_device(struct acpi_device *adev)
+static inline void acpi_put_acpi_dev(struct acpi_device *adev)
 {
        acpi_dev_put(adev);
 }
index a71d73a..85a35f6 100644 (file)
@@ -509,6 +509,7 @@ int acpi_dev_get_resources(struct acpi_device *adev, struct list_head *list,
                           void *preproc_data);
 int acpi_dev_get_dma_resources(struct acpi_device *adev,
                               struct list_head *list);
+int acpi_dev_get_memory_resources(struct acpi_device *adev, struct list_head *list);
 int acpi_dev_filter_resource_type(struct acpi_resource *ares,
                                  unsigned long types);
 
index 126d082..e605a2c 100644 (file)
@@ -27,9 +27,14 @@ struct tps68470_regulator_platform_data {
        const struct regulator_init_data *reg_init_data[TPS68470_NUM_REGULATORS];
 };
 
-struct tps68470_clk_platform_data {
+struct tps68470_clk_consumer {
        const char *consumer_dev_name;
        const char *consumer_con_id;
 };
 
+struct tps68470_clk_platform_data {
+       unsigned int n_consumers;
+       struct tps68470_clk_consumer consumers[];
+};
+
 #endif