Merge tag 'devprop-4.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 5 Sep 2017 19:50:00 +0000 (12:50 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 5 Sep 2017 19:50:00 +0000 (12:50 -0700)
Pull device properties framework updates from Rafael Wysocki:
 "These introduce fwnode operations for all of the separate types of
  'firmware nodes' that can be handled by the device properties
  framework, make the framework use const fwnode arguments all over, add
  a helper for the consolidated handling of node references and switch
  over the framework to the new UUID API.

  Specifics:

   - Introduce fwnode operations for all of the separate types of
     'firmware nodes' that can be handled by the device properties
     framework and drop the type field from struct fwnode_handle (Sakari
     Ailus, Arnd Bergmann).

   - Make the device properties framework use const fwnode arguments
     where possible (Sakari Ailus).

   - Add a helper for the consolidated handling of node references to
     the device properties framework (Sakari Ailus).

   - Switch over the ACPI part of the device properties framework to the
     new UUID API (Andy Shevchenko)"

* tag 'devprop-4.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  ACPI: device property: Switch to use new generic UUID API
  device property: export irqchip_fwnode_ops
  device property: Introduce fwnode_property_get_reference_args
  device property: Constify fwnode property API
  device property: Constify argument to pset fwnode backend
  ACPI: Constify internal fwnode arguments
  ACPI: Constify acpi_bus helper functions, switch to macros
  ACPI: Prepare for constifying acpi_get_next_subnode() fwnode argument
  device property: Get rid of struct fwnode_handle type field
  ACPI: Use IS_ERR_OR_NULL() instead of non-NULL check in is_acpi_data_node()

1  2 
drivers/acpi/property.c
drivers/acpi/scan.c
drivers/of/property.c
include/acpi/acpi_bus.h
include/linux/acpi.h
include/linux/irqdomain.h
kernel/irq/irqdomain.c

diff --combined drivers/acpi/property.c
  
  #include "internal.h"
  
- static int acpi_data_get_property_array(struct acpi_device_data *data,
+ static int acpi_data_get_property_array(const struct acpi_device_data *data,
                                        const char *name,
                                        acpi_object_type type,
                                        const union acpi_object **obj);
  
- /* ACPI _DSD device properties UUID: daffd814-6eba-4d8c-8a91-bc9bbf4aa301 */
- static const u8 prp_uuid[16] = {
-       0x14, 0xd8, 0xff, 0xda, 0xba, 0x6e, 0x8c, 0x4d,
-       0x8a, 0x91, 0xbc, 0x9b, 0xbf, 0x4a, 0xa3, 0x01
- };
- /* ACPI _DSD data subnodes UUID: dbb8e3e6-5886-4ba6-8795-1319f52a966b */
- static const u8 ads_uuid[16] = {
-       0xe6, 0xe3, 0xb8, 0xdb, 0x86, 0x58, 0xa6, 0x4b,
-       0x87, 0x95, 0x13, 0x19, 0xf5, 0x2a, 0x96, 0x6b
- };
+ /* ACPI _DSD device properties GUID: daffd814-6eba-4d8c-8a91-bc9bbf4aa301 */
+ static const guid_t prp_guid =
+       GUID_INIT(0xdaffd814, 0x6eba, 0x4d8c,
+                 0x8a, 0x91, 0xbc, 0x9b, 0xbf, 0x4a, 0xa3, 0x01);
+ /* ACPI _DSD data subnodes GUID: dbb8e3e6-5886-4ba6-8795-1319f52a966b */
+ static const guid_t ads_guid =
+       GUID_INIT(0xdbb8e3e6, 0x5886, 0x4ba6,
+                 0x87, 0x95, 0x13, 0x19, 0xf5, 0x2a, 0x96, 0x6b);
  
  static bool acpi_enumerate_nondev_subnodes(acpi_handle scope,
                                           const union acpi_object *desc,
@@@ -56,8 -54,7 +54,7 @@@ static bool acpi_nondev_subnode_extract
                return false;
  
        dn->name = link->package.elements[0].string.pointer;
-       dn->fwnode.type = FWNODE_ACPI_DATA;
-       dn->fwnode.ops = &acpi_fwnode_ops;
+       dn->fwnode.ops = &acpi_data_fwnode_ops;
        dn->parent = parent;
        INIT_LIST_HEAD(&dn->data.subnodes);
  
@@@ -190,22 -187,23 +187,23 @@@ static bool acpi_enumerate_nondev_subno
  {
        int i;
  
-       /* Look for the ACPI data subnodes UUID. */
+       /* Look for the ACPI data subnodes GUID. */
        for (i = 0; i < desc->package.count; i += 2) {
-               const union acpi_object *uuid, *links;
+               const union acpi_object *guid, *links;
  
-               uuid = &desc->package.elements[i];
+               guid = &desc->package.elements[i];
                links = &desc->package.elements[i + 1];
  
                /*
-                * The first element must be a UUID and the second one must be
+                * The first element must be a GUID and the second one must be
                 * a package.
                 */
-               if (uuid->type != ACPI_TYPE_BUFFER || uuid->buffer.length != 16
-                   || links->type != ACPI_TYPE_PACKAGE)
+               if (guid->type != ACPI_TYPE_BUFFER ||
+                   guid->buffer.length != 16 ||
+                   links->type != ACPI_TYPE_PACKAGE)
                        break;
  
-               if (memcmp(uuid->buffer.pointer, ads_uuid, sizeof(ads_uuid)))
+               if (!guid_equal((guid_t *)guid->buffer.pointer, &ads_guid))
                        continue;
  
                return acpi_add_nondev_subnodes(scope, links, &data->subnodes,
@@@ -298,26 -296,27 +296,27 @@@ static bool acpi_extract_properties(con
        if (desc->package.count % 2)
                return false;
  
-       /* Look for the device properties UUID. */
+       /* Look for the device properties GUID. */
        for (i = 0; i < desc->package.count; i += 2) {
-               const union acpi_object *uuid, *properties;
+               const union acpi_object *guid, *properties;
  
-               uuid = &desc->package.elements[i];
+               guid = &desc->package.elements[i];
                properties = &desc->package.elements[i + 1];
  
                /*
-                * The first element must be a UUID and the second one must be
+                * The first element must be a GUID and the second one must be
                 * a package.
                 */
-               if (uuid->type != ACPI_TYPE_BUFFER || uuid->buffer.length != 16
-                   || properties->type != ACPI_TYPE_PACKAGE)
+               if (guid->type != ACPI_TYPE_BUFFER ||
+                   guid->buffer.length != 16 ||
+                   properties->type != ACPI_TYPE_PACKAGE)
                        break;
  
-               if (memcmp(uuid->buffer.pointer, prp_uuid, sizeof(prp_uuid)))
+               if (!guid_equal((guid_t *)guid->buffer.pointer, &prp_guid))
                        continue;
  
                /*
-                * We found the matching UUID. Now validate the format of the
+                * We found the matching GUID. Now validate the format of the
                 * package immediately following it.
                 */
                if (!acpi_properties_format_valid(properties))
@@@ -339,9 -338,6 +338,9 @@@ void acpi_init_properties(struct acpi_d
  
        INIT_LIST_HEAD(&adev->data.subnodes);
  
 +      if (!adev->handle)
 +              return;
 +
        /*
         * Check if ACPI_DT_NAMESPACE_HID is present and inthat case we fill in
         * Device Tree compatible properties for this device.
        if (acpi_of && !adev->flags.of_compatible_ok)
                acpi_handle_info(adev->handle,
                         ACPI_DT_NAMESPACE_HID " requires 'compatible' property\n");
 +
 +      if (!adev->data.pointer)
 +              acpi_extract_apple_properties(adev);
  }
  
  static void acpi_destroy_nondev_subnodes(struct list_head *list)
@@@ -424,7 -417,7 +423,7 @@@ void acpi_free_properties(struct acpi_d
   *         %-EINVAL if the property doesn't exist,
   *         %-EPROTO if the property value type doesn't match @type.
   */
- static int acpi_data_get_property(struct acpi_device_data *data,
+ static int acpi_data_get_property(const struct acpi_device_data *data,
                                  const char *name, acpi_object_type type,
                                  const union acpi_object **obj)
  {
   * @type: Expected property type.
   * @obj: Location to store the property value (if not %NULL).
   */
- int acpi_dev_get_property(struct acpi_device *adev, const char *name,
+ int acpi_dev_get_property(const struct acpi_device *adev, const char *name,
                          acpi_object_type type, const union acpi_object **obj)
  {
        return adev ? acpi_data_get_property(&adev->data, name, type, obj) : -EINVAL;
  }
  EXPORT_SYMBOL_GPL(acpi_dev_get_property);
  
- static struct acpi_device_data *acpi_device_data_of_node(struct fwnode_handle *fwnode)
+ static const struct acpi_device_data *
+ acpi_device_data_of_node(const struct fwnode_handle *fwnode)
  {
-       if (fwnode->type == FWNODE_ACPI) {
-               struct acpi_device *adev = to_acpi_device_node(fwnode);
+       if (is_acpi_device_node(fwnode)) {
+               const struct acpi_device *adev = to_acpi_device_node(fwnode);
                return &adev->data;
-       } else if (fwnode->type == FWNODE_ACPI_DATA) {
-               struct acpi_data_node *dn = to_acpi_data_node(fwnode);
+       } else if (is_acpi_data_node(fwnode)) {
+               const struct acpi_data_node *dn = to_acpi_data_node(fwnode);
                return &dn->data;
        }
        return NULL;
   * @propname: Name of the property.
   * @valptr: Location to store a pointer to the property value (if not %NULL).
   */
- int acpi_node_prop_get(struct fwnode_handle *fwnode, const char *propname,
-                      void **valptr)
+ int acpi_node_prop_get(const struct fwnode_handle *fwnode,
+                      const char *propname, void **valptr)
  {
        return acpi_data_get_property(acpi_device_data_of_node(fwnode),
                                      propname, ACPI_TYPE_ANY,
   *         %-EPROTO if the property is not a package or the type of its elements
   *           doesn't match @type.
   */
- static int acpi_data_get_property_array(struct acpi_device_data *data,
+ static int acpi_data_get_property_array(const struct acpi_device_data *data,
                                        const char *name,
                                        acpi_object_type type,
                                        const union acpi_object **obj)
   *
   * Return: %0 on success, negative error code on failure.
   */
- int __acpi_node_get_property_reference(struct fwnode_handle *fwnode,
+ int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode,
        const char *propname, size_t index, size_t num_args,
        struct acpi_reference_args *args)
  {
        const union acpi_object *element, *end;
        const union acpi_object *obj;
-       struct acpi_device_data *data;
+       const struct acpi_device_data *data;
        struct acpi_device *device;
        int ret, idx = 0;
  
  }
  EXPORT_SYMBOL_GPL(__acpi_node_get_property_reference);
  
- static int acpi_data_prop_read_single(struct acpi_device_data *data,
+ static int acpi_data_prop_read_single(const struct acpi_device_data *data,
                                      const char *propname,
                                      enum dev_prop_type proptype, void *val)
  {
@@@ -819,7 -813,7 +819,7 @@@ static int acpi_copy_property_array_str
        return nval;
  }
  
- static int acpi_data_prop_read(struct acpi_device_data *data,
+ static int acpi_data_prop_read(const struct acpi_device_data *data,
                               const char *propname,
                               enum dev_prop_type proptype,
                               void *val, size_t nval)
        return ret;
  }
  
- int acpi_dev_prop_read(struct acpi_device *adev, const char *propname,
+ int acpi_dev_prop_read(const struct acpi_device *adev, const char *propname,
                       enum dev_prop_type proptype, void *val, size_t nval)
  {
        return adev ? acpi_data_prop_read(&adev->data, propname, proptype, val, nval) : -EINVAL;
   * of the property.  Otherwise, read at most @nval values to the array at the
   * location pointed to by @val.
   */
- int acpi_node_prop_read(struct fwnode_handle *fwnode,  const char *propname,
-                       enum dev_prop_type proptype, void *val, size_t nval)
+ int acpi_node_prop_read(const struct fwnode_handle *fwnode,
+                       const char *propname, enum dev_prop_type proptype,
+                       void *val, size_t nval)
  {
        return acpi_data_prop_read(acpi_device_data_of_node(fwnode),
                                   propname, proptype, val, nval);
   * @fwnode: Firmware node to find the next child node for.
   * @child: Handle to one of the device's child nodes or a null handle.
   */
- struct fwnode_handle *acpi_get_next_subnode(struct fwnode_handle *fwnode,
+ struct fwnode_handle *acpi_get_next_subnode(const struct fwnode_handle *fwnode,
                                            struct fwnode_handle *child)
  {
-       struct acpi_device *adev = to_acpi_device_node(fwnode);
-       struct list_head *head, *next;
+       const struct acpi_device *adev = to_acpi_device_node(fwnode);
+       struct acpi_device *child_adev = NULL;
+       const struct list_head *head;
+       struct list_head *next;
  
-       if (!child || child->type == FWNODE_ACPI) {
+       if (!child || is_acpi_device_node(child)) {
                if (adev)
                        head = &adev->children;
                else
                        goto nondev;
  
                if (child) {
-                       adev = to_acpi_device_node(child);
-                       next = adev->node.next;
+                       child_adev = to_acpi_device_node(child);
+                       next = child_adev->node.next;
                        if (next == head) {
                                child = NULL;
                                goto nondev;
                        }
-                       adev = list_entry(next, struct acpi_device, node);
+                       child_adev = list_entry(next, struct acpi_device, node);
                } else {
-                       adev = list_first_entry(head, struct acpi_device, node);
+                       child_adev = list_first_entry(head, struct acpi_device,
+                                                     node);
                }
-               return acpi_fwnode_handle(adev);
+               return acpi_fwnode_handle(child_adev);
        }
  
   nondev:
-       if (!child || child->type == FWNODE_ACPI_DATA) {
-               struct acpi_data_node *data = to_acpi_data_node(fwnode);
+       if (!child || is_acpi_data_node(child)) {
+               const struct acpi_data_node *data = to_acpi_data_node(fwnode);
                struct acpi_data_node *dn;
  
-               if (adev)
-                       head = &adev->data.subnodes;
+               if (child_adev)
+                       head = &child_adev->data.subnodes;
                else if (data)
                        head = &data->data.subnodes;
                else
   * Returns parent node of an ACPI device or data firmware node or %NULL if
   * not available.
   */
- struct fwnode_handle *acpi_node_get_parent(struct fwnode_handle *fwnode)
+ struct fwnode_handle *acpi_node_get_parent(const struct fwnode_handle *fwnode)
  {
        if (is_acpi_data_node(fwnode)) {
                /* All data nodes have parent pointer so just return that */
   * %NULL if there is no next endpoint, ERR_PTR() in case of error. In case
   * of success the next endpoint is returned.
   */
- struct fwnode_handle *acpi_graph_get_next_endpoint(struct fwnode_handle *fwnode,
-                                                  struct fwnode_handle *prev)
+ struct fwnode_handle *acpi_graph_get_next_endpoint(
+       const struct fwnode_handle *fwnode, struct fwnode_handle *prev)
  {
        struct fwnode_handle *port = NULL;
        struct fwnode_handle *endpoint;
   * the child node on success, NULL otherwise.
   */
  static struct fwnode_handle *acpi_graph_get_child_prop_value(
-       struct fwnode_handle *fwnode, const char *prop_name, unsigned int val)
+       const struct fwnode_handle *fwnode, const char *prop_name,
+       unsigned int val)
  {
        struct fwnode_handle *child;
  
        fwnode_for_each_child_node(fwnode, child) {
                u32 nr;
  
 -              if (!fwnode_property_read_u32(fwnode, prop_name, &nr))
 +              if (fwnode_property_read_u32(child, prop_name, &nr))
                        continue;
  
                if (val == nr)
   * fields requested by the caller. Returns %0 in case of success and
   * negative errno otherwise.
   */
- int acpi_graph_get_remote_endpoint(struct fwnode_handle *fwnode,
+ int acpi_graph_get_remote_endpoint(const struct fwnode_handle *__fwnode,
                                   struct fwnode_handle **parent,
                                   struct fwnode_handle **port,
                                   struct fwnode_handle **endpoint)
  {
+       struct fwnode_handle *fwnode;
        unsigned int port_nr, endpoint_nr;
        struct acpi_reference_args args;
        int ret;
  
        memset(&args, 0, sizeof(args));
-       ret = acpi_node_get_property_reference(fwnode, "remote-endpoint", 0,
+       ret = acpi_node_get_property_reference(__fwnode, "remote-endpoint", 0,
                                               &args);
        if (ret)
                return ret;
        return 0;
  }
  
- static bool acpi_fwnode_device_is_available(struct fwnode_handle *fwnode)
+ static bool acpi_fwnode_device_is_available(const struct fwnode_handle *fwnode)
  {
        if (!is_acpi_device_node(fwnode))
                return false;
        return acpi_device_is_present(to_acpi_device_node(fwnode));
  }
  
- static bool acpi_fwnode_property_present(struct fwnode_handle *fwnode,
+ static bool acpi_fwnode_property_present(const struct fwnode_handle *fwnode,
                                         const char *propname)
  {
        return !acpi_node_prop_get(fwnode, propname, NULL);
  }
  
- static int acpi_fwnode_property_read_int_array(struct fwnode_handle *fwnode,
-                                              const char *propname,
-                                              unsigned int elem_size,
-                                              void *val, size_t nval)
+ static int
+ acpi_fwnode_property_read_int_array(const struct fwnode_handle *fwnode,
+                                   const char *propname,
+                                   unsigned int elem_size, void *val,
+                                   size_t nval)
  {
        enum dev_prop_type type;
  
        return acpi_node_prop_read(fwnode, propname, type, val, nval);
  }
  
- static int acpi_fwnode_property_read_string_array(struct fwnode_handle *fwnode,
-                                                 const char *propname,
-                                                 const char **val, size_t nval)
+ static int
+ acpi_fwnode_property_read_string_array(const struct fwnode_handle *fwnode,
+                                      const char *propname, const char **val,
+                                      size_t nval)
  {
        return acpi_node_prop_read(fwnode, propname, DEV_PROP_STRING,
                                   val, nval);
  }
  
  static struct fwnode_handle *
- acpi_fwnode_get_named_child_node(struct fwnode_handle *fwnode,
+ acpi_fwnode_get_named_child_node(const struct fwnode_handle *fwnode,
                                 const char *childname)
  {
        struct fwnode_handle *child;
        return NULL;
  }
  
+ static int
+ acpi_fwnode_get_reference_args(const struct fwnode_handle *fwnode,
+                              const char *prop, const char *nargs_prop,
+                              unsigned int args_count, unsigned int index,
+                              struct fwnode_reference_args *args)
+ {
+       struct acpi_reference_args acpi_args;
+       unsigned int i;
+       int ret;
+       ret = __acpi_node_get_property_reference(fwnode, prop, index,
+                                                args_count, &acpi_args);
+       if (ret < 0)
+               return ret;
+       if (!args)
+               return 0;
+       args->nargs = acpi_args.nargs;
+       args->fwnode = acpi_fwnode_handle(acpi_args.adev);
+       for (i = 0; i < NR_FWNODE_REFERENCE_ARGS; i++)
+               args->args[i] = i < acpi_args.nargs ? acpi_args.args[i] : 0;
+       return 0;
+ }
  static struct fwnode_handle *
- acpi_fwnode_graph_get_next_endpoint(struct fwnode_handle *fwnode,
+ acpi_fwnode_graph_get_next_endpoint(const struct fwnode_handle *fwnode,
                                    struct fwnode_handle *prev)
  {
        struct fwnode_handle *endpoint;
  }
  
  static struct fwnode_handle *
- acpi_fwnode_graph_get_remote_endpoint(struct fwnode_handle *fwnode)
+ acpi_fwnode_graph_get_remote_endpoint(const struct fwnode_handle *fwnode)
  {
        struct fwnode_handle *endpoint = NULL;
  
        return endpoint;
  }
  
- static int acpi_fwnode_graph_parse_endpoint(struct fwnode_handle *fwnode,
+ static struct fwnode_handle *
+ acpi_fwnode_get_parent(struct fwnode_handle *fwnode)
+ {
+       return acpi_node_get_parent(fwnode);
+ }
+ static int acpi_fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode,
                                            struct fwnode_endpoint *endpoint)
  {
        struct fwnode_handle *port_fwnode = fwnode_get_parent(fwnode);
        return 0;
  }
  
- const struct fwnode_operations acpi_fwnode_ops = {
-       .device_is_available = acpi_fwnode_device_is_available,
-       .property_present = acpi_fwnode_property_present,
-       .property_read_int_array = acpi_fwnode_property_read_int_array,
-       .property_read_string_array = acpi_fwnode_property_read_string_array,
-       .get_parent = acpi_node_get_parent,
-       .get_next_child_node = acpi_get_next_subnode,
-       .get_named_child_node = acpi_fwnode_get_named_child_node,
-       .graph_get_next_endpoint = acpi_fwnode_graph_get_next_endpoint,
-       .graph_get_remote_endpoint = acpi_fwnode_graph_get_remote_endpoint,
-       .graph_get_port_parent = acpi_node_get_parent,
-       .graph_parse_endpoint = acpi_fwnode_graph_parse_endpoint,
- };
+ #define DECLARE_ACPI_FWNODE_OPS(ops) \
+       const struct fwnode_operations ops = {                          \
+               .device_is_available = acpi_fwnode_device_is_available, \
+               .property_present = acpi_fwnode_property_present,       \
+               .property_read_int_array =                              \
+                       acpi_fwnode_property_read_int_array,            \
+               .property_read_string_array =                           \
+                       acpi_fwnode_property_read_string_array,         \
+               .get_parent = acpi_node_get_parent,                     \
+               .get_next_child_node = acpi_get_next_subnode,           \
+               .get_named_child_node = acpi_fwnode_get_named_child_node, \
+               .get_reference_args = acpi_fwnode_get_reference_args,   \
+               .graph_get_next_endpoint =                              \
+                       acpi_fwnode_graph_get_next_endpoint,            \
+               .graph_get_remote_endpoint =                            \
+                       acpi_fwnode_graph_get_remote_endpoint,          \
+               .graph_get_port_parent = acpi_fwnode_get_parent,        \
+               .graph_parse_endpoint = acpi_fwnode_graph_parse_endpoint, \
+       };                                                              \
+       EXPORT_SYMBOL_GPL(ops)
+ DECLARE_ACPI_FWNODE_OPS(acpi_device_fwnode_ops);
+ DECLARE_ACPI_FWNODE_OPS(acpi_data_fwnode_ops);
+ const struct fwnode_operations acpi_static_fwnode_ops;
diff --combined drivers/acpi/scan.c
@@@ -13,7 -13,6 +13,7 @@@
  #include <linux/dmi.h>
  #include <linux/nls.h>
  #include <linux/dma-mapping.h>
 +#include <linux/platform_data/x86/apple.h>
  
  #include <asm/pgtable.h>
  
@@@ -1360,85 -1359,6 +1360,85 @@@ enum dev_dma_attr acpi_get_dma_attr(str
                return DEV_DMA_NON_COHERENT;
  }
  
 +/**
 + * acpi_dma_get_range() - Get device DMA parameters.
 + *
 + * @dev: device to configure
 + * @dma_addr: pointer device DMA address result
 + * @offset: pointer to the DMA offset result
 + * @size: pointer to DMA range size result
 + *
 + * Evaluate DMA regions and return respectively DMA region start, offset
 + * and size in dma_addr, offset and size on parsing success; it does not
 + * update the passed in values on failure.
 + *
 + * Return 0 on success, < 0 on failure.
 + */
 +int acpi_dma_get_range(struct device *dev, u64 *dma_addr, u64 *offset,
 +                     u64 *size)
 +{
 +      struct acpi_device *adev;
 +      LIST_HEAD(list);
 +      struct resource_entry *rentry;
 +      int ret;
 +      struct device *dma_dev = dev;
 +      u64 len, dma_start = U64_MAX, dma_end = 0, dma_offset = 0;
 +
 +      /*
 +       * Walk the device tree chasing an ACPI companion with a _DMA
 +       * object while we go. Stop if we find a device with an ACPI
 +       * companion containing a _DMA method.
 +       */
 +      do {
 +              adev = ACPI_COMPANION(dma_dev);
 +              if (adev && acpi_has_method(adev->handle, METHOD_NAME__DMA))
 +                      break;
 +
 +              dma_dev = dma_dev->parent;
 +      } while (dma_dev);
 +
 +      if (!dma_dev)
 +              return -ENODEV;
 +
 +      if (!acpi_has_method(adev->handle, METHOD_NAME__CRS)) {
 +              acpi_handle_warn(adev->handle, "_DMA is valid only if _CRS is present\n");
 +              return -EINVAL;
 +      }
 +
 +      ret = acpi_dev_get_dma_resources(adev, &list);
 +      if (ret > 0) {
 +              list_for_each_entry(rentry, &list, node) {
 +                      if (dma_offset && rentry->offset != dma_offset) {
 +                              ret = -EINVAL;
 +                              dev_warn(dma_dev, "Can't handle multiple windows with different offsets\n");
 +                              goto out;
 +                      }
 +                      dma_offset = rentry->offset;
 +
 +                      /* Take lower and upper limits */
 +                      if (rentry->res->start < dma_start)
 +                              dma_start = rentry->res->start;
 +                      if (rentry->res->end > dma_end)
 +                              dma_end = rentry->res->end;
 +              }
 +
 +              if (dma_start >= dma_end) {
 +                      ret = -EINVAL;
 +                      dev_dbg(dma_dev, "Invalid DMA regions configuration\n");
 +                      goto out;
 +              }
 +
 +              *dma_addr = dma_start - dma_offset;
 +              len = dma_end - dma_start;
 +              *size = max(len, len + 1);
 +              *offset = dma_offset;
 +      }
 + out:
 +      acpi_dev_free_resource_list(&list);
 +
 +      return ret >= 0 ? 0 : ret;
 +}
 +
  /**
   * acpi_dma_configure - Set-up DMA configuration for the device.
   * @dev: The pointer to the device
  int acpi_dma_configure(struct device *dev, enum dev_dma_attr attr)
  {
        const struct iommu_ops *iommu;
 -      u64 size;
 +      u64 dma_addr = 0, size = 0;
  
 -      iort_set_dma_mask(dev);
 +      iort_dma_setup(dev, &dma_addr, &size);
  
        iommu = iort_iommu_configure(dev);
        if (IS_ERR(iommu) && PTR_ERR(iommu) == -EPROBE_DEFER)
                return -EPROBE_DEFER;
  
 -      size = max(dev->coherent_dma_mask, dev->coherent_dma_mask + 1);
 -      /*
 -       * Assume dma valid range starts at 0 and covers the whole
 -       * coherent_dma_mask.
 -       */
 -      arch_setup_dma_ops(dev, 0, size, iommu, attr == DEV_DMA_COHERENT);
 +      arch_setup_dma_ops(dev, dma_addr, size,
 +                              iommu, attr == DEV_DMA_COHERENT);
  
        return 0;
  }
@@@ -1528,12 -1452,6 +1528,12 @@@ static bool acpi_is_spi_i2c_slave(struc
        struct list_head resource_list;
        bool is_spi_i2c_slave = false;
  
 +      /* Macs use device properties in lieu of _CRS resources */
 +      if (x86_apple_machine &&
 +          (fwnode_property_present(&device->fwnode, "spiSclkPeriod") ||
 +           fwnode_property_present(&device->fwnode, "i2cAddress")))
 +              return true;
 +
        INIT_LIST_HEAD(&resource_list);
        acpi_dev_get_resources(device, &resource_list, acpi_check_spi_i2c_slave,
                               &is_spi_i2c_slave);
@@@ -1549,8 -1467,7 +1549,7 @@@ void acpi_init_device_object(struct acp
        device->device_type = type;
        device->handle = handle;
        device->parent = acpi_bus_get_parent(handle);
-       device->fwnode.type = FWNODE_ACPI;
-       device->fwnode.ops = &acpi_fwnode_ops;
+       device->fwnode.ops = &acpi_device_fwnode_ops;
        acpi_set_device_status(device, sta);
        acpi_device_get_busid(device);
        acpi_set_pnp_ids(handle, &device->pnp, type);
@@@ -2140,9 -2057,6 +2139,9 @@@ int __init acpi_scan_init(void
                        acpi_get_spcr_uart_addr();
        }
  
 +      acpi_gpe_apply_masked_gpes();
 +      acpi_update_all_gpes();
 +
        mutex_lock(&acpi_scan_lock);
        /*
         * Enumerate devices in the ACPI namespace.
                }
        }
  
 -      acpi_gpe_apply_masked_gpes();
 -      acpi_update_all_gpes();
 -      acpi_ec_ecdt_start();
 -
        acpi_scan_initialized = true;
  
   out:
diff --combined drivers/of/property.c
@@@ -708,15 -708,6 +708,15 @@@ struct device_node *of_graph_get_port_p
  {
        unsigned int depth;
  
 +      if (!node)
 +              return NULL;
 +
 +      /*
 +       * Preserve usecount for passed in node as of_get_next_parent()
 +       * will do of_node_put() on it.
 +       */
 +      of_node_get(node);
 +
        /* Walk 3 levels up only if there is 'ports' node. */
        for (depth = 3; depth && node; depth--) {
                node = of_get_next_parent(node);
@@@ -737,16 -728,12 +737,16 @@@ EXPORT_SYMBOL(of_graph_get_port_parent)
  struct device_node *of_graph_get_remote_port_parent(
                               const struct device_node *node)
  {
 -      struct device_node *np;
 +      struct device_node *np, *pp;
  
        /* Get remote endpoint node. */
        np = of_graph_get_remote_endpoint(node);
  
 -      return of_graph_get_port_parent(np);
 +      pp = of_graph_get_port_parent(np);
 +
 +      of_node_put(np);
 +
 +      return pp;
  }
  EXPORT_SYMBOL(of_graph_get_remote_port_parent);
  
@@@ -828,23 -815,23 +828,23 @@@ static void of_fwnode_put(struct fwnode
        of_node_put(to_of_node(fwnode));
  }
  
- static bool of_fwnode_device_is_available(struct fwnode_handle *fwnode)
+ static bool of_fwnode_device_is_available(const struct fwnode_handle *fwnode)
  {
        return of_device_is_available(to_of_node(fwnode));
  }
  
- static bool of_fwnode_property_present(struct fwnode_handle *fwnode,
+ static bool of_fwnode_property_present(const struct fwnode_handle *fwnode,
                                       const char *propname)
  {
        return of_property_read_bool(to_of_node(fwnode), propname);
  }
  
- static int of_fwnode_property_read_int_array(struct fwnode_handle *fwnode,
+ static int of_fwnode_property_read_int_array(const struct fwnode_handle *fwnode,
                                             const char *propname,
                                             unsigned int elem_size, void *val,
                                             size_t nval)
  {
-       struct device_node *node = to_of_node(fwnode);
+       const struct device_node *node = to_of_node(fwnode);
  
        if (!val)
                return of_property_count_elems_of_size(node, propname,
        return -ENXIO;
  }
  
- static int of_fwnode_property_read_string_array(struct fwnode_handle *fwnode,
-                                               const char *propname,
-                                               const char **val, size_t nval)
+ static int
+ of_fwnode_property_read_string_array(const struct fwnode_handle *fwnode,
+                                    const char *propname, const char **val,
+                                    size_t nval)
  {
-       struct device_node *node = to_of_node(fwnode);
+       const struct device_node *node = to_of_node(fwnode);
  
        return val ?
                of_property_read_string_array(node, propname, val, nval) :
                of_property_count_strings(node, propname);
  }
  
- static struct fwnode_handle *of_fwnode_get_parent(struct fwnode_handle *fwnode)
+ static struct fwnode_handle *
+ of_fwnode_get_parent(const struct fwnode_handle *fwnode)
  {
        return of_fwnode_handle(of_get_parent(to_of_node(fwnode)));
  }
  
  static struct fwnode_handle *
- of_fwnode_get_next_child_node(struct fwnode_handle *fwnode,
+ of_fwnode_get_next_child_node(const struct fwnode_handle *fwnode,
                              struct fwnode_handle *child)
  {
        return of_fwnode_handle(of_get_next_available_child(to_of_node(fwnode),
  }
  
  static struct fwnode_handle *
- of_fwnode_get_named_child_node(struct fwnode_handle *fwnode,
+ of_fwnode_get_named_child_node(const struct fwnode_handle *fwnode,
                               const char *childname)
  {
-       struct device_node *node = to_of_node(fwnode);
+       const struct device_node *node = to_of_node(fwnode);
        struct device_node *child;
  
        for_each_available_child_of_node(node, child)
        return NULL;
  }
  
+ static int
+ of_fwnode_get_reference_args(const struct fwnode_handle *fwnode,
+                            const char *prop, const char *nargs_prop,
+                            unsigned int nargs, unsigned int index,
+                            struct fwnode_reference_args *args)
+ {
+       struct of_phandle_args of_args;
+       unsigned int i;
+       int ret;
+       if (nargs_prop)
+               ret = of_parse_phandle_with_args(to_of_node(fwnode), prop,
+                                                nargs_prop, index, &of_args);
+       else
+               ret = of_parse_phandle_with_fixed_args(to_of_node(fwnode), prop,
+                                                      nargs, index, &of_args);
+       if (ret < 0)
+               return ret;
+       if (!args)
+               return 0;
+       args->nargs = of_args.args_count;
+       args->fwnode = of_fwnode_handle(of_args.np);
+       for (i = 0; i < NR_FWNODE_REFERENCE_ARGS; i++)
+               args->args[i] = i < of_args.args_count ? of_args.args[i] : 0;
+       return 0;
+ }
  static struct fwnode_handle *
- of_fwnode_graph_get_next_endpoint(struct fwnode_handle *fwnode,
+ of_fwnode_graph_get_next_endpoint(const struct fwnode_handle *fwnode,
                                  struct fwnode_handle *prev)
  {
        return of_fwnode_handle(of_graph_get_next_endpoint(to_of_node(fwnode),
  }
  
  static struct fwnode_handle *
- of_fwnode_graph_get_remote_endpoint(struct fwnode_handle *fwnode)
+ of_fwnode_graph_get_remote_endpoint(const struct fwnode_handle *fwnode)
  {
        return of_fwnode_handle(of_parse_phandle(to_of_node(fwnode),
                                                 "remote-endpoint", 0));
@@@ -934,10 -953,10 +966,10 @@@ of_fwnode_graph_get_port_parent(struct 
        return of_fwnode_handle(of_get_next_parent(np));
  }
  
- static int of_fwnode_graph_parse_endpoint(struct fwnode_handle *fwnode,
+ static int of_fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode,
                                          struct fwnode_endpoint *endpoint)
  {
-       struct device_node *node = to_of_node(fwnode);
+       const struct device_node *node = to_of_node(fwnode);
        struct device_node *port_node = of_get_parent(node);
  
        endpoint->local_fwnode = fwnode;
@@@ -960,8 -979,10 +992,10 @@@ const struct fwnode_operations of_fwnod
        .get_parent = of_fwnode_get_parent,
        .get_next_child_node = of_fwnode_get_next_child_node,
        .get_named_child_node = of_fwnode_get_named_child_node,
+       .get_reference_args = of_fwnode_get_reference_args,
        .graph_get_next_endpoint = of_fwnode_graph_get_next_endpoint,
        .graph_get_remote_endpoint = of_fwnode_graph_get_remote_endpoint,
        .graph_get_port_parent = of_fwnode_graph_get_port_parent,
        .graph_parse_endpoint = of_fwnode_graph_parse_endpoint,
  };
+ EXPORT_SYMBOL_GPL(of_fwnode_ops);
diff --combined include/acpi/acpi_bus.h
@@@ -316,6 -316,7 +316,6 @@@ struct acpi_device_perf 
  struct acpi_device_wakeup_flags {
        u8 valid:1;             /* Can successfully enable wakeup? */
        u8 notifier_present:1;  /* Wake-up notify handler has been installed */
 -      u8 enabled:1;           /* Enabled for wakeup */
  };
  
  struct acpi_device_wakeup_context {
@@@ -332,7 -333,6 +332,7 @@@ struct acpi_device_wakeup 
        struct acpi_device_wakeup_context context;
        struct wakeup_source *ws;
        int prepare_count;
 +      int enable_count;
  };
  
  struct acpi_device_physical_node {
@@@ -395,35 -395,55 +395,55 @@@ struct acpi_data_node 
        struct completion kobj_done;
  };
  
- static inline bool is_acpi_node(struct fwnode_handle *fwnode)
- {
-       return !IS_ERR_OR_NULL(fwnode) && (fwnode->type == FWNODE_ACPI
-               || fwnode->type == FWNODE_ACPI_DATA);
- }
+ extern const struct fwnode_operations acpi_device_fwnode_ops;
+ extern const struct fwnode_operations acpi_data_fwnode_ops;
+ extern const struct fwnode_operations acpi_static_fwnode_ops;
  
- static inline bool is_acpi_device_node(struct fwnode_handle *fwnode)
+ static inline bool is_acpi_node(const struct fwnode_handle *fwnode)
  {
-       return !IS_ERR_OR_NULL(fwnode) && fwnode->type == FWNODE_ACPI;
+       return !IS_ERR_OR_NULL(fwnode) &&
+               (fwnode->ops == &acpi_device_fwnode_ops
+                || fwnode->ops == &acpi_data_fwnode_ops);
  }
  
- static inline struct acpi_device *to_acpi_device_node(struct fwnode_handle *fwnode)
+ static inline bool is_acpi_device_node(const struct fwnode_handle *fwnode)
  {
-       return is_acpi_device_node(fwnode) ?
-               container_of(fwnode, struct acpi_device, fwnode) : NULL;
+       return !IS_ERR_OR_NULL(fwnode) &&
+               fwnode->ops == &acpi_device_fwnode_ops;
  }
  
- static inline bool is_acpi_data_node(struct fwnode_handle *fwnode)
+ #define to_acpi_device_node(__fwnode)                                 \
+       ({                                                              \
+               typeof(__fwnode) __to_acpi_device_node_fwnode = __fwnode; \
+                                                                       \
+               is_acpi_device_node(__to_acpi_device_node_fwnode) ?     \
+                       container_of(__to_acpi_device_node_fwnode,      \
+                                    struct acpi_device, fwnode) :      \
+                       NULL;                                           \
+       })
+ static inline bool is_acpi_data_node(const struct fwnode_handle *fwnode)
  {
-       return fwnode && fwnode->type == FWNODE_ACPI_DATA;
+       return !IS_ERR_OR_NULL(fwnode) && fwnode->ops == &acpi_data_fwnode_ops;
  }
  
- static inline struct acpi_data_node *to_acpi_data_node(struct fwnode_handle *fwnode)
+ #define to_acpi_data_node(__fwnode)                                   \
+       ({                                                              \
+               typeof(__fwnode) __to_acpi_data_node_fwnode = __fwnode; \
+                                                                       \
+               is_acpi_data_node(__to_acpi_data_node_fwnode) ?         \
+                       container_of(__to_acpi_data_node_fwnode,        \
+                                    struct acpi_data_node, fwnode) :   \
+                       NULL;                                           \
+       })
+ static inline bool is_acpi_static_node(const struct fwnode_handle *fwnode)
  {
-       return is_acpi_data_node(fwnode) ?
-               container_of(fwnode, struct acpi_data_node, fwnode) : NULL;
+       return !IS_ERR_OR_NULL(fwnode) &&
+               fwnode->ops == &acpi_static_fwnode_ops;
  }
  
- static inline bool acpi_data_node_match(struct fwnode_handle *fwnode,
+ static inline bool acpi_data_node_match(const struct fwnode_handle *fwnode,
                                        const char *name)
  {
        return is_acpi_data_node(fwnode) ?
@@@ -578,8 -598,6 +598,8 @@@ struct acpi_pci_root 
  
  bool acpi_dma_supported(struct acpi_device *adev);
  enum dev_dma_attr acpi_get_dma_attr(struct acpi_device *adev);
 +int acpi_dma_get_range(struct device *dev, u64 *dma_addr, u64 *offset,
 +                     u64 *size);
  int acpi_dma_configure(struct device *dev, enum dev_dma_attr attr);
  void acpi_dma_deconfigure(struct device *dev);
  
@@@ -608,7 -626,6 +628,7 @@@ acpi_status acpi_remove_pm_notifier(str
  bool acpi_pm_device_can_wakeup(struct device *dev);
  int acpi_pm_device_sleep_state(struct device *, int *, int);
  int acpi_pm_set_device_wakeup(struct device *dev, bool enable);
 +int acpi_pm_set_bridge_wakeup(struct device *dev, bool enable);
  #else
  static inline void acpi_pm_wakeup_event(struct device *dev)
  {
@@@ -639,10 -656,6 +659,10 @@@ static inline int acpi_pm_set_device_wa
  {
        return -ENODEV;
  }
 +static inline int acpi_pm_set_bridge_wakeup(struct device *dev, bool enable)
 +{
 +      return -ENODEV;
 +}
  #endif
  
  #ifdef CONFIG_ACPI_SLEEP
diff --combined include/linux/acpi.h
@@@ -57,9 -57,6 +57,6 @@@ static inline acpi_handle acpi_device_h
        acpi_fwnode_handle(adev) : NULL)
  #define ACPI_HANDLE(dev)              acpi_device_handle(ACPI_COMPANION(dev))
  
- extern const struct fwnode_operations acpi_fwnode_ops;
  static inline struct fwnode_handle *acpi_alloc_fwnode_static(void)
  {
        struct fwnode_handle *fwnode;
        if (!fwnode)
                return NULL;
  
-       fwnode->type = FWNODE_ACPI_STATIC;
-       fwnode->ops = &acpi_fwnode_ops;
+       fwnode->ops = &acpi_static_fwnode_ops;
  
        return fwnode;
  }
  
  static inline void acpi_free_fwnode_static(struct fwnode_handle *fwnode)
  {
-       if (WARN_ON(!fwnode || fwnode->type != FWNODE_ACPI_STATIC))
+       if (WARN_ON(!is_acpi_static_node(fwnode)))
                return;
  
        kfree(fwnode);
@@@ -228,8 -224,8 +224,8 @@@ struct acpi_subtable_proc 
        int count;
  };
  
 -char * __acpi_map_table (unsigned long phys_addr, unsigned long size);
 -void __acpi_unmap_table(char *map, unsigned long size);
 +void __iomem *__acpi_map_table(unsigned long phys, unsigned long size);
 +void __acpi_unmap_table(void __iomem *map, unsigned long size);
  int early_acpi_boot_init(void);
  int acpi_boot_init (void);
  void acpi_boot_table_init (void);
@@@ -427,8 -423,6 +423,8 @@@ void acpi_dev_free_resource_list(struc
  int acpi_dev_get_resources(struct acpi_device *adev, struct list_head *list,
                           int (*preproc)(struct acpi_resource *, void *),
                           void *preproc_data);
 +int acpi_dev_get_dma_resources(struct acpi_device *adev,
 +                             struct list_head *list);
  int acpi_dev_filter_resource_type(struct acpi_resource *ares,
                                  unsigned long types);
  
@@@ -558,25 -552,6 +554,25 @@@ extern acpi_status acpi_pci_osc_control
  #define ACPI_OST_SC_DRIVER_LOAD_FAILURE               0x81
  #define ACPI_OST_SC_INSERT_NOT_SUPPORTED      0x82
  
 +enum acpi_predicate {
 +      all_versions,
 +      less_than_or_equal,
 +      equal,
 +      greater_than_or_equal,
 +};
 +
 +/* Table must be terminted by a NULL entry */
 +struct acpi_platform_list {
 +      char    oem_id[ACPI_OEM_ID_SIZE+1];
 +      char    oem_table_id[ACPI_OEM_TABLE_ID_SIZE+1];
 +      u32     oem_revision;
 +      char    *table;
 +      enum acpi_predicate pred;
 +      char    *reason;
 +      u32     data;
 +};
 +int acpi_match_platform_list(const struct acpi_platform_list *plat);
 +
  extern void acpi_early_init(void);
  extern void acpi_subsystem_init(void);
  
@@@ -795,12 -770,6 +791,12 @@@ static inline enum dev_dma_attr acpi_ge
        return DEV_DMA_NOT_SUPPORTED;
  }
  
 +static inline int acpi_dma_get_range(struct device *dev, u64 *dma_addr,
 +                                   u64 *offset, u64 *size)
 +{
 +      return -ENODEV;
 +}
 +
  static inline int acpi_dma_configure(struct device *dev,
                                     enum dev_dma_attr attr)
  {
@@@ -1034,13 -1003,14 +1030,14 @@@ struct acpi_reference_args 
  };
  
  #ifdef CONFIG_ACPI
- int acpi_dev_get_property(struct acpi_device *adev, const char *name,
+ int acpi_dev_get_property(const struct acpi_device *adev, const char *name,
                          acpi_object_type type, const union acpi_object **obj);
- int __acpi_node_get_property_reference(struct fwnode_handle *fwnode,
+ int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode,
                                const char *name, size_t index, size_t num_args,
                                struct acpi_reference_args *args);
  
- static inline int acpi_node_get_property_reference(struct fwnode_handle *fwnode,
+ static inline int acpi_node_get_property_reference(
+                               const struct fwnode_handle *fwnode,
                                const char *name, size_t index,
                                struct acpi_reference_args *args)
  {
                MAX_ACPI_REFERENCE_ARGS, args);
  }
  
- int acpi_node_prop_get(struct fwnode_handle *fwnode, const char *propname,
+ int acpi_node_prop_get(const struct fwnode_handle *fwnode, const char *propname,
                       void **valptr);
- int acpi_dev_prop_read_single(struct acpi_device *adev, const char *propname,
-                             enum dev_prop_type proptype, void *val);
- int acpi_node_prop_read(struct fwnode_handle *fwnode, const char *propname,
-                       enum dev_prop_type proptype, void *val, size_t nval);
- int acpi_dev_prop_read(struct acpi_device *adev, const char *propname,
+ int acpi_dev_prop_read_single(struct acpi_device *adev,
+                             const char *propname, enum dev_prop_type proptype,
+                             void *val);
+ int acpi_node_prop_read(const struct fwnode_handle *fwnode,
+                       const char *propname, enum dev_prop_type proptype,
+                       void *val, size_t nval);
+ int acpi_dev_prop_read(const struct acpi_device *adev, const char *propname,
                       enum dev_prop_type proptype, void *val, size_t nval);
  
- struct fwnode_handle *acpi_get_next_subnode(struct fwnode_handle *fwnode,
+ struct fwnode_handle *acpi_get_next_subnode(const struct fwnode_handle *fwnode,
                                            struct fwnode_handle *child);
- struct fwnode_handle *acpi_node_get_parent(struct fwnode_handle *fwnode);
+ struct fwnode_handle *acpi_node_get_parent(const struct fwnode_handle *fwnode);
  
- struct fwnode_handle *acpi_graph_get_next_endpoint(struct fwnode_handle *fwnode,
-                                                  struct fwnode_handle *prev);
- int acpi_graph_get_remote_endpoint(struct fwnode_handle *fwnode,
+ struct fwnode_handle *
+ acpi_graph_get_next_endpoint(const struct fwnode_handle *fwnode,
+                            struct fwnode_handle *prev);
+ int acpi_graph_get_remote_endpoint(const struct fwnode_handle *fwnode,
                                   struct fwnode_handle **remote,
                                   struct fwnode_handle **port,
                                   struct fwnode_handle **endpoint);
@@@ -1131,35 -1104,36 +1131,36 @@@ static inline int acpi_dev_get_property
  }
  
  static inline int
- __acpi_node_get_property_reference(struct fwnode_handle *fwnode,
+ __acpi_node_get_property_reference(const struct fwnode_handle *fwnode,
                                const char *name, size_t index, size_t num_args,
                                struct acpi_reference_args *args)
  {
        return -ENXIO;
  }
  
- static inline int acpi_node_get_property_reference(struct fwnode_handle *fwnode,
-                               const char *name, size_t index,
-                               struct acpi_reference_args *args)
+ static inline int
+ acpi_node_get_property_reference(const struct fwnode_handle *fwnode,
+                                const char *name, size_t index,
+                                struct acpi_reference_args *args)
  {
        return -ENXIO;
  }
  
- static inline int acpi_node_prop_get(struct fwnode_handle *fwnode,
+ static inline int acpi_node_prop_get(const struct fwnode_handle *fwnode,
                                     const char *propname,
                                     void **valptr)
  {
        return -ENXIO;
  }
  
- static inline int acpi_dev_prop_get(struct acpi_device *adev,
+ static inline int acpi_dev_prop_get(const struct acpi_device *adev,
                                    const char *propname,
                                    void **valptr)
  {
        return -ENXIO;
  }
  
- static inline int acpi_dev_prop_read_single(struct acpi_device *adev,
+ static inline int acpi_dev_prop_read_single(const struct acpi_device *adev,
                                            const char *propname,
                                            enum dev_prop_type proptype,
                                            void *val)
        return -ENXIO;
  }
  
- static inline int acpi_node_prop_read(struct fwnode_handle *fwnode,
+ static inline int acpi_node_prop_read(const struct fwnode_handle *fwnode,
                                      const char *propname,
                                      enum dev_prop_type proptype,
                                      void *val, size_t nval)
        return -ENXIO;
  }
  
- static inline int acpi_dev_prop_read(struct acpi_device *adev,
+ static inline int acpi_dev_prop_read(const struct acpi_device *adev,
                                     const char *propname,
                                     enum dev_prop_type proptype,
                                     void *val, size_t nval)
  }
  
  static inline struct fwnode_handle *
- acpi_get_next_subnode(struct fwnode_handle *fwnode, struct fwnode_handle *child)
+ acpi_get_next_subnode(const struct fwnode_handle *fwnode,
+                     struct fwnode_handle *child)
  {
        return NULL;
  }
  
  static inline struct fwnode_handle *
- acpi_node_get_parent(struct fwnode_handle *fwnode)
+ acpi_node_get_parent(const struct fwnode_handle *fwnode)
  {
        return NULL;
  }
  
  static inline struct fwnode_handle *
- acpi_graph_get_next_endpoint(struct fwnode_handle *fwnode,
+ acpi_graph_get_next_endpoint(const struct fwnode_handle *fwnode,
                             struct fwnode_handle *prev)
  {
        return ERR_PTR(-ENXIO);
  }
  
  static inline int
- acpi_graph_get_remote_endpoint(struct fwnode_handle *fwnode,
+ acpi_graph_get_remote_endpoint(const struct fwnode_handle *fwnode,
                               struct fwnode_handle **remote,
                               struct fwnode_handle **port,
                               struct fwnode_handle **endpoint)
@@@ -1236,7 -1211,6 +1238,7 @@@ static inline bool acpi_has_watchdog(vo
  #endif
  
  #ifdef CONFIG_ACPI_SPCR_TABLE
 +extern bool qdf2400_e44_present;
  int parse_spcr(bool earlycon);
  #else
  static inline int parse_spcr(bool earlycon) { return 0; }
@@@ -265,9 -265,11 +265,11 @@@ static inline struct fwnode_handle *of_
        return node ? &node->fwnode : NULL;
  }
  
+ extern const struct fwnode_operations irqchip_fwnode_ops;
  static inline bool is_fwnode_irqchip(struct fwnode_handle *fwnode)
  {
-       return fwnode && fwnode->type == FWNODE_IRQCHIP;
+       return fwnode && fwnode->ops == &irqchip_fwnode_ops;
  }
  
  extern void irq_domain_update_bus_token(struct irq_domain *domain,
@@@ -460,9 -462,6 +462,9 @@@ extern void irq_domain_free_irqs_common
  extern void irq_domain_free_irqs_top(struct irq_domain *domain,
                                     unsigned int virq, unsigned int nr_irqs);
  
 +extern int irq_domain_push_irq(struct irq_domain *domain, int virq, void *arg);
 +extern int irq_domain_pop_irq(struct irq_domain *domain, int virq);
 +
  extern int irq_domain_alloc_irqs_parent(struct irq_domain *domain,
                                        unsigned int irq_base,
                                        unsigned int nr_irqs, void *arg);
diff --combined kernel/irq/irqdomain.c
@@@ -41,6 -41,9 +41,9 @@@ static inline void debugfs_add_domain_d
  static inline void debugfs_remove_domain_dir(struct irq_domain *d) { }
  #endif
  
+ const struct fwnode_operations irqchip_fwnode_ops;
+ EXPORT_SYMBOL_GPL(irqchip_fwnode_ops);
  /**
   * irq_domain_alloc_fwnode - Allocate a fwnode_handle suitable for
   *                           identifying an irq domain
@@@ -86,7 -89,7 +89,7 @@@ struct fwnode_handle *__irq_domain_allo
        fwid->type = type;
        fwid->name = n;
        fwid->data = data;
-       fwid->fwnode.type = FWNODE_IRQCHIP;
+       fwid->fwnode.ops = &irqchip_fwnode_ops;
        return &fwid->fwnode;
  }
  EXPORT_SYMBOL_GPL(__irq_domain_alloc_fwnode);
@@@ -193,10 -196,8 +196,8 @@@ struct irq_domain *__irq_domain_add(str
        }
  
        if (!domain->name) {
-               if (fwnode) {
-                       pr_err("Invalid fwnode type (%d) for irqdomain\n",
-                              fwnode->type);
-               }
+               if (fwnode)
+                       pr_err("Invalid fwnode type for irqdomain\n");
                domain->name = kasprintf(GFP_KERNEL, "unknown-%d",
                                         atomic_inc_return(&unknown_domains));
                if (!domain->name) {
@@@ -455,31 -456,6 +456,31 @@@ void irq_set_default_host(struct irq_do
  }
  EXPORT_SYMBOL_GPL(irq_set_default_host);
  
 +static void irq_domain_clear_mapping(struct irq_domain *domain,
 +                                   irq_hw_number_t hwirq)
 +{
 +      if (hwirq < domain->revmap_size) {
 +              domain->linear_revmap[hwirq] = 0;
 +      } else {
 +              mutex_lock(&revmap_trees_mutex);
 +              radix_tree_delete(&domain->revmap_tree, hwirq);
 +              mutex_unlock(&revmap_trees_mutex);
 +      }
 +}
 +
 +static void irq_domain_set_mapping(struct irq_domain *domain,
 +                                 irq_hw_number_t hwirq,
 +                                 struct irq_data *irq_data)
 +{
 +      if (hwirq < domain->revmap_size) {
 +              domain->linear_revmap[hwirq] = irq_data->irq;
 +      } else {
 +              mutex_lock(&revmap_trees_mutex);
 +              radix_tree_insert(&domain->revmap_tree, hwirq, irq_data);
 +              mutex_unlock(&revmap_trees_mutex);
 +      }
 +}
 +
  void irq_domain_disassociate(struct irq_domain *domain, unsigned int irq)
  {
        struct irq_data *irq_data = irq_get_irq_data(irq);
        domain->mapcount--;
  
        /* Clear reverse map for this hwirq */
 -      if (hwirq < domain->revmap_size) {
 -              domain->linear_revmap[hwirq] = 0;
 -      } else {
 -              mutex_lock(&revmap_trees_mutex);
 -              radix_tree_delete(&domain->revmap_tree, hwirq);
 -              mutex_unlock(&revmap_trees_mutex);
 -      }
 +      irq_domain_clear_mapping(domain, hwirq);
  }
  
  int irq_domain_associate(struct irq_domain *domain, unsigned int virq,
        }
  
        domain->mapcount++;
 -      if (hwirq < domain->revmap_size) {
 -              domain->linear_revmap[hwirq] = virq;
 -      } else {
 -              mutex_lock(&revmap_trees_mutex);
 -              radix_tree_insert(&domain->revmap_tree, hwirq, irq_data);
 -              mutex_unlock(&revmap_trees_mutex);
 -      }
 +      irq_domain_set_mapping(domain, hwirq, irq_data);
        mutex_unlock(&irq_domain_mutex);
  
        irq_clear_status_flags(virq, IRQ_NOREQUEST);
@@@ -1151,9 -1139,16 +1152,9 @@@ static void irq_domain_insert_irq(int v
  
        for (data = irq_get_irq_data(virq); data; data = data->parent_data) {
                struct irq_domain *domain = data->domain;
 -              irq_hw_number_t hwirq = data->hwirq;
  
                domain->mapcount++;
 -              if (hwirq < domain->revmap_size) {
 -                      domain->linear_revmap[hwirq] = virq;
 -              } else {
 -                      mutex_lock(&revmap_trees_mutex);
 -                      radix_tree_insert(&domain->revmap_tree, hwirq, data);
 -                      mutex_unlock(&revmap_trees_mutex);
 -              }
 +              irq_domain_set_mapping(domain, data->hwirq, data);
  
                /* If not already assigned, give the domain the chip's name */
                if (!domain->name && data->chip)
@@@ -1177,7 -1172,13 +1178,7 @@@ static void irq_domain_remove_irq(int v
                irq_hw_number_t hwirq = data->hwirq;
  
                domain->mapcount--;
 -              if (hwirq < domain->revmap_size) {
 -                      domain->linear_revmap[hwirq] = 0;
 -              } else {
 -                      mutex_lock(&revmap_trees_mutex);
 -                      radix_tree_delete(&domain->revmap_tree, hwirq);
 -                      mutex_unlock(&revmap_trees_mutex);
 -              }
 +              irq_domain_clear_mapping(domain, hwirq);
        }
  }
  
@@@ -1362,8 -1363,7 +1363,8 @@@ static void irq_domain_free_irqs_hierar
                                           unsigned int irq_base,
                                           unsigned int nr_irqs)
  {
 -      domain->ops->free(domain, irq_base, nr_irqs);
 +      if (domain->ops->free)
 +              domain->ops->free(domain, irq_base, nr_irqs);
  }
  
  int irq_domain_alloc_irqs_hierarchy(struct irq_domain *domain,
@@@ -1449,175 -1449,6 +1450,175 @@@ out_free_desc
        return ret;
  }
  
 +/* The irq_data was moved, fix the revmap to refer to the new location */
 +static void irq_domain_fix_revmap(struct irq_data *d)
 +{
 +      void **slot;
 +
 +      if (d->hwirq < d->domain->revmap_size)
 +              return; /* Not using radix tree. */
 +
 +      /* Fix up the revmap. */
 +      mutex_lock(&revmap_trees_mutex);
 +      slot = radix_tree_lookup_slot(&d->domain->revmap_tree, d->hwirq);
 +      if (slot)
 +              radix_tree_replace_slot(&d->domain->revmap_tree, slot, d);
 +      mutex_unlock(&revmap_trees_mutex);
 +}
 +
 +/**
 + * irq_domain_push_irq() - Push a domain in to the top of a hierarchy.
 + * @domain:   Domain to push.
 + * @virq:     Irq to push the domain in to.
 + * @arg:      Passed to the irq_domain_ops alloc() function.
 + *
 + * For an already existing irqdomain hierarchy, as might be obtained
 + * via a call to pci_enable_msix(), add an additional domain to the
 + * head of the processing chain.  Must be called before request_irq()
 + * has been called.
 + */
 +int irq_domain_push_irq(struct irq_domain *domain, int virq, void *arg)
 +{
 +      struct irq_data *child_irq_data;
 +      struct irq_data *root_irq_data = irq_get_irq_data(virq);
 +      struct irq_desc *desc;
 +      int rv = 0;
 +
 +      /*
 +       * Check that no action has been set, which indicates the virq
 +       * is in a state where this function doesn't have to deal with
 +       * races between interrupt handling and maintaining the
 +       * hierarchy.  This will catch gross misuse.  Attempting to
 +       * make the check race free would require holding locks across
 +       * calls to struct irq_domain_ops->alloc(), which could lead
 +       * to deadlock, so we just do a simple check before starting.
 +       */
 +      desc = irq_to_desc(virq);
 +      if (!desc)
 +              return -EINVAL;
 +      if (WARN_ON(desc->action))
 +              return -EBUSY;
 +
 +      if (domain == NULL)
 +              return -EINVAL;
 +
 +      if (WARN_ON(!irq_domain_is_hierarchy(domain)))
 +              return -EINVAL;
 +
 +      if (!root_irq_data)
 +              return -EINVAL;
 +
 +      if (domain->parent != root_irq_data->domain)
 +              return -EINVAL;
 +
 +      child_irq_data = kzalloc_node(sizeof(*child_irq_data), GFP_KERNEL,
 +                                    irq_data_get_node(root_irq_data));
 +      if (!child_irq_data)
 +              return -ENOMEM;
 +
 +      mutex_lock(&irq_domain_mutex);
 +
 +      /* Copy the original irq_data. */
 +      *child_irq_data = *root_irq_data;
 +
 +      /*
 +       * Overwrite the root_irq_data, which is embedded in struct
 +       * irq_desc, with values for this domain.
 +       */
 +      root_irq_data->parent_data = child_irq_data;
 +      root_irq_data->domain = domain;
 +      root_irq_data->mask = 0;
 +      root_irq_data->hwirq = 0;
 +      root_irq_data->chip = NULL;
 +      root_irq_data->chip_data = NULL;
 +
 +      /* May (probably does) set hwirq, chip, etc. */
 +      rv = irq_domain_alloc_irqs_hierarchy(domain, virq, 1, arg);
 +      if (rv) {
 +              /* Restore the original irq_data. */
 +              *root_irq_data = *child_irq_data;
 +              goto error;
 +      }
 +
 +      irq_domain_fix_revmap(child_irq_data);
 +      irq_domain_set_mapping(domain, root_irq_data->hwirq, root_irq_data);
 +
 +error:
 +      mutex_unlock(&irq_domain_mutex);
 +
 +      return rv;
 +}
 +EXPORT_SYMBOL_GPL(irq_domain_push_irq);
 +
 +/**
 + * irq_domain_pop_irq() - Remove a domain from the top of a hierarchy.
 + * @domain:   Domain to remove.
 + * @virq:     Irq to remove the domain from.
 + *
 + * Undo the effects of a call to irq_domain_push_irq().  Must be
 + * called either before request_irq() or after free_irq().
 + */
 +int irq_domain_pop_irq(struct irq_domain *domain, int virq)
 +{
 +      struct irq_data *root_irq_data = irq_get_irq_data(virq);
 +      struct irq_data *child_irq_data;
 +      struct irq_data *tmp_irq_data;
 +      struct irq_desc *desc;
 +
 +      /*
 +       * Check that no action is set, which indicates the virq is in
 +       * a state where this function doesn't have to deal with races
 +       * between interrupt handling and maintaining the hierarchy.
 +       * This will catch gross misuse.  Attempting to make the check
 +       * race free would require holding locks across calls to
 +       * struct irq_domain_ops->free(), which could lead to
 +       * deadlock, so we just do a simple check before starting.
 +       */
 +      desc = irq_to_desc(virq);
 +      if (!desc)
 +              return -EINVAL;
 +      if (WARN_ON(desc->action))
 +              return -EBUSY;
 +
 +      if (domain == NULL)
 +              return -EINVAL;
 +
 +      if (!root_irq_data)
 +              return -EINVAL;
 +
 +      tmp_irq_data = irq_domain_get_irq_data(domain, virq);
 +
 +      /* We can only "pop" if this domain is at the top of the list */
 +      if (WARN_ON(root_irq_data != tmp_irq_data))
 +              return -EINVAL;
 +
 +      if (WARN_ON(root_irq_data->domain != domain))
 +              return -EINVAL;
 +
 +      child_irq_data = root_irq_data->parent_data;
 +      if (WARN_ON(!child_irq_data))
 +              return -EINVAL;
 +
 +      mutex_lock(&irq_domain_mutex);
 +
 +      root_irq_data->parent_data = NULL;
 +
 +      irq_domain_clear_mapping(domain, root_irq_data->hwirq);
 +      irq_domain_free_irqs_hierarchy(domain, virq, 1);
 +
 +      /* Restore the original irq_data. */
 +      *root_irq_data = *child_irq_data;
 +
 +      irq_domain_fix_revmap(root_irq_data);
 +
 +      mutex_unlock(&irq_domain_mutex);
 +
 +      kfree(child_irq_data);
 +
 +      return 0;
 +}
 +EXPORT_SYMBOL_GPL(irq_domain_pop_irq);
 +
  /**
   * irq_domain_free_irqs - Free IRQ number and associated data structures
   * @virq:     base IRQ number