]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/base/core.c
Revert "driver core: Add sync_state driver/bus callback"
[linux.git] / drivers / base / core.c
index 636058bbf48a3d902dc7d7f64b902d6e31abf5c3..de775c7a4d7c10528f9ec1c06ef6432fd638cedc 100644 (file)
@@ -44,6 +44,8 @@ early_param("sysfs.deprecated", sysfs_deprecated_setup);
 #endif
 
 /* Device links support. */
+static LIST_HEAD(wait_for_suppliers);
+static DEFINE_MUTEX(wfs_lock);
 
 #ifdef CONFIG_SRCU
 static DEFINE_MUTEX(device_links_lock);
@@ -124,6 +126,50 @@ static int device_is_dependent(struct device *dev, void *target)
        return ret;
 }
 
+static void device_link_init_status(struct device_link *link,
+                                   struct device *consumer,
+                                   struct device *supplier)
+{
+       switch (supplier->links.status) {
+       case DL_DEV_PROBING:
+               switch (consumer->links.status) {
+               case DL_DEV_PROBING:
+                       /*
+                        * A consumer driver can create a link to a supplier
+                        * that has not completed its probing yet as long as it
+                        * knows that the supplier is already functional (for
+                        * example, it has just acquired some resources from the
+                        * supplier).
+                        */
+                       link->status = DL_STATE_CONSUMER_PROBE;
+                       break;
+               default:
+                       link->status = DL_STATE_DORMANT;
+                       break;
+               }
+               break;
+       case DL_DEV_DRIVER_BOUND:
+               switch (consumer->links.status) {
+               case DL_DEV_PROBING:
+                       link->status = DL_STATE_CONSUMER_PROBE;
+                       break;
+               case DL_DEV_DRIVER_BOUND:
+                       link->status = DL_STATE_ACTIVE;
+                       break;
+               default:
+                       link->status = DL_STATE_AVAILABLE;
+                       break;
+               }
+               break;
+       case DL_DEV_UNBINDING:
+               link->status = DL_STATE_SUPPLIER_UNBIND;
+               break;
+       default:
+               link->status = DL_STATE_DORMANT;
+               break;
+       }
+}
+
 static int device_reorder_to_tail(struct device *dev, void *not_used)
 {
        struct device_link *link;
@@ -165,6 +211,13 @@ void device_pm_move_to_tail(struct device *dev)
        device_links_read_unlock(idx);
 }
 
+#define DL_MANAGED_LINK_FLAGS (DL_FLAG_AUTOREMOVE_CONSUMER | \
+                              DL_FLAG_AUTOREMOVE_SUPPLIER | \
+                              DL_FLAG_AUTOPROBE_CONSUMER)
+
+#define DL_ADD_VALID_FLAGS (DL_MANAGED_LINK_FLAGS | DL_FLAG_STATELESS | \
+                           DL_FLAG_PM_RUNTIME | DL_FLAG_RPM_ACTIVE)
+
 /**
  * device_link_add - Create a link between two devices.
  * @consumer: Consumer end of the link.
@@ -179,9 +232,9 @@ void device_pm_move_to_tail(struct device *dev)
  * of the link.  If DL_FLAG_PM_RUNTIME is not set, DL_FLAG_RPM_ACTIVE will be
  * ignored.
  *
- * If DL_FLAG_STATELESS is set in @flags, the link is not going to be managed by
- * the driver core and, in particular, the caller of this function is expected
- * to drop the reference to the link acquired by it directly.
+ * If DL_FLAG_STATELESS is set in @flags, the caller of this function is
+ * expected to release the link returned by it directly with the help of either
+ * device_link_del() or device_link_remove().
  *
  * If that flag is not set, however, the caller of this function is handing the
  * management of the link over to the driver core entirely and its return value
@@ -201,9 +254,16 @@ void device_pm_move_to_tail(struct device *dev)
  * be used to request the driver core to automaticall probe for a consmer
  * driver after successfully binding a driver to the supplier device.
  *
- * The combination of DL_FLAG_STATELESS and either DL_FLAG_AUTOREMOVE_CONSUMER
- * or DL_FLAG_AUTOREMOVE_SUPPLIER set in @flags at the same time is invalid and
- * will cause NULL to be returned upfront.
+ * The combination of DL_FLAG_STATELESS and one of DL_FLAG_AUTOREMOVE_CONSUMER,
+ * DL_FLAG_AUTOREMOVE_SUPPLIER, or DL_FLAG_AUTOPROBE_CONSUMER set in @flags at
+ * the same time is invalid and will cause NULL to be returned upfront.
+ * However, if a device link between the given @consumer and @supplier pair
+ * exists already when this function is called for them, the existing link will
+ * be returned regardless of its current type and status (the link's flags may
+ * be modified then).  The caller of this function is then expected to treat
+ * the link as though it has just been created, so (in particular) if
+ * DL_FLAG_STATELESS was passed in @flags, the link needs to be released
+ * explicitly when not needed any more (as stated above).
  *
  * A side effect of the link creation is re-ordering of dpm_list and the
  * devices_kset list by moving the consumer device and all devices depending
@@ -219,11 +279,8 @@ struct device_link *device_link_add(struct device *consumer,
 {
        struct device_link *link;
 
-       if (!consumer || !supplier ||
-           (flags & DL_FLAG_STATELESS &&
-            flags & (DL_FLAG_AUTOREMOVE_CONSUMER |
-                     DL_FLAG_AUTOREMOVE_SUPPLIER |
-                     DL_FLAG_AUTOPROBE_CONSUMER)) ||
+       if (!consumer || !supplier || flags & ~DL_ADD_VALID_FLAGS ||
+           (flags & DL_FLAG_STATELESS && flags & DL_MANAGED_LINK_FLAGS) ||
            (flags & DL_FLAG_AUTOPROBE_CONSUMER &&
             flags & (DL_FLAG_AUTOREMOVE_CONSUMER |
                      DL_FLAG_AUTOREMOVE_SUPPLIER)))
@@ -236,6 +293,9 @@ struct device_link *device_link_add(struct device *consumer,
                }
        }
 
+       if (!(flags & DL_FLAG_STATELESS))
+               flags |= DL_FLAG_MANAGED;
+
        device_links_write_lock();
        device_pm_lock();
 
@@ -262,15 +322,6 @@ struct device_link *device_link_add(struct device *consumer,
                if (link->consumer != consumer)
                        continue;
 
-               /*
-                * Don't return a stateless link if the caller wants a stateful
-                * one and vice versa.
-                */
-               if (WARN_ON((flags & DL_FLAG_STATELESS) != (link->flags & DL_FLAG_STATELESS))) {
-                       link = NULL;
-                       goto out;
-               }
-
                if (flags & DL_FLAG_PM_RUNTIME) {
                        if (!(link->flags & DL_FLAG_PM_RUNTIME)) {
                                pm_runtime_new_link(consumer);
@@ -281,6 +332,7 @@ struct device_link *device_link_add(struct device *consumer,
                }
 
                if (flags & DL_FLAG_STATELESS) {
+                       link->flags |= DL_FLAG_STATELESS;
                        kref_get(&link->kref);
                        goto out;
                }
@@ -299,6 +351,11 @@ struct device_link *device_link_add(struct device *consumer,
                        link->flags &= ~(DL_FLAG_AUTOREMOVE_CONSUMER |
                                         DL_FLAG_AUTOREMOVE_SUPPLIER);
                }
+               if (!(link->flags & DL_FLAG_MANAGED)) {
+                       kref_get(&link->kref);
+                       link->flags |= DL_FLAG_MANAGED;
+                       device_link_init_status(link, consumer, supplier);
+               }
                goto out;
        }
 
@@ -325,48 +382,10 @@ struct device_link *device_link_add(struct device *consumer,
        kref_init(&link->kref);
 
        /* Determine the initial link state. */
-       if (flags & DL_FLAG_STATELESS) {
+       if (flags & DL_FLAG_STATELESS)
                link->status = DL_STATE_NONE;
-       } else {
-               switch (supplier->links.status) {
-               case DL_DEV_PROBING:
-                       switch (consumer->links.status) {
-                       case DL_DEV_PROBING:
-                               /*
-                                * A consumer driver can create a link to a
-                                * supplier that has not completed its probing
-                                * yet as long as it knows that the supplier is
-                                * already functional (for example, it has just
-                                * acquired some resources from the supplier).
-                                */
-                               link->status = DL_STATE_CONSUMER_PROBE;
-                               break;
-                       default:
-                               link->status = DL_STATE_DORMANT;
-                               break;
-                       }
-                       break;
-               case DL_DEV_DRIVER_BOUND:
-                       switch (consumer->links.status) {
-                       case DL_DEV_PROBING:
-                               link->status = DL_STATE_CONSUMER_PROBE;
-                               break;
-                       case DL_DEV_DRIVER_BOUND:
-                               link->status = DL_STATE_ACTIVE;
-                               break;
-                       default:
-                               link->status = DL_STATE_AVAILABLE;
-                               break;
-                       }
-                       break;
-               case DL_DEV_UNBINDING:
-                       link->status = DL_STATE_SUPPLIER_UNBIND;
-                       break;
-               default:
-                       link->status = DL_STATE_DORMANT;
-                       break;
-               }
-       }
+       else
+               device_link_init_status(link, consumer, supplier);
 
        /*
         * Some callers expect the link creation during consumer driver probe to
@@ -401,6 +420,71 @@ struct device_link *device_link_add(struct device *consumer,
 }
 EXPORT_SYMBOL_GPL(device_link_add);
 
+/**
+ * device_link_wait_for_supplier - Mark device as waiting for supplier
+ * @consumer: Consumer device
+ *
+ * Marks the consumer device as waiting for suppliers to become available. The
+ * consumer device will never be probed until it's unmarked as waiting for
+ * suppliers. The caller is responsible for adding the link to the supplier
+ * once the supplier device is present.
+ *
+ * This function is NOT meant to be called from the probe function of the
+ * consumer but rather from code that creates/adds the consumer device.
+ */
+static void device_link_wait_for_supplier(struct device *consumer)
+{
+       mutex_lock(&wfs_lock);
+       list_add_tail(&consumer->links.needs_suppliers, &wait_for_suppliers);
+       mutex_unlock(&wfs_lock);
+}
+
+/**
+ * device_link_remove_from_wfs - Unmark device as waiting for supplier
+ * @consumer: Consumer device
+ *
+ * Unmark the consumer device as waiting for suppliers to become available.
+ */
+void device_link_remove_from_wfs(struct device *consumer)
+{
+       mutex_lock(&wfs_lock);
+       list_del_init(&consumer->links.needs_suppliers);
+       mutex_unlock(&wfs_lock);
+}
+
+/**
+ * device_link_check_waiting_consumers - Try to unmark waiting consumers
+ *
+ * Loops through all consumers waiting on suppliers and tries to add all their
+ * supplier links. If that succeeds, the consumer device is unmarked as waiting
+ * for suppliers. Otherwise, they are left marked as waiting on suppliers,
+ *
+ * The add_links bus callback is expected to return 0 if it has found and added
+ * all the supplier links for the consumer device. It should return an error if
+ * it isn't able to do so.
+ *
+ * The caller of device_link_wait_for_supplier() is expected to call this once
+ * it's aware of potential suppliers becoming available.
+ */
+static void device_link_check_waiting_consumers(void)
+{
+       struct device *dev, *tmp;
+       int ret;
+
+       mutex_lock(&wfs_lock);
+       list_for_each_entry_safe(dev, tmp, &wait_for_suppliers,
+                                links.needs_suppliers) {
+               ret = 0;
+               if (dev->has_edit_links)
+                       ret = driver_edit_links(dev);
+               else if (dev->bus->add_links)
+                       ret = dev->bus->add_links(dev);
+               if (!ret)
+                       list_del_init(&dev->links.needs_suppliers);
+       }
+       mutex_unlock(&wfs_lock);
+}
+
 static void device_link_free(struct device_link *link)
 {
        while (refcount_dec_not_one(&link->rpm_active))
@@ -528,17 +612,30 @@ static void device_links_missing_supplier(struct device *dev)
  * mark the link as "consumer probe in progress" to make the supplier removal
  * wait for us to complete (or bad things may happen).
  *
- * Links with the DL_FLAG_STATELESS flag set are ignored.
+ * Links without the DL_FLAG_MANAGED flag set are ignored.
  */
 int device_links_check_suppliers(struct device *dev)
 {
        struct device_link *link;
        int ret = 0;
 
+       /*
+        * If a device is waiting for one or more suppliers (in
+        * wait_for_suppliers list), it is not ready to probe yet. So just
+        * return -EPROBE_DEFER without having to check the links with existing
+        * suppliers.
+        */
+       mutex_lock(&wfs_lock);
+       if (!list_empty(&dev->links.needs_suppliers)) {
+               mutex_unlock(&wfs_lock);
+               return -EPROBE_DEFER;
+       }
+       mutex_unlock(&wfs_lock);
+
        device_links_write_lock();
 
        list_for_each_entry(link, &dev->links.suppliers, c_node) {
-               if (link->flags & DL_FLAG_STATELESS)
+               if (!(link->flags & DL_FLAG_MANAGED))
                        continue;
 
                if (link->status != DL_STATE_AVAILABLE) {
@@ -563,7 +660,7 @@ int device_links_check_suppliers(struct device *dev)
  *
  * Also change the status of @dev's links to suppliers to "active".
  *
- * Links with the DL_FLAG_STATELESS flag set are ignored.
+ * Links without the DL_FLAG_MANAGED flag set are ignored.
  */
 void device_links_driver_bound(struct device *dev)
 {
@@ -572,7 +669,7 @@ void device_links_driver_bound(struct device *dev)
        device_links_write_lock();
 
        list_for_each_entry(link, &dev->links.consumers, s_node) {
-               if (link->flags & DL_FLAG_STATELESS)
+               if (!(link->flags & DL_FLAG_MANAGED))
                        continue;
 
                /*
@@ -593,7 +690,7 @@ void device_links_driver_bound(struct device *dev)
        }
 
        list_for_each_entry(link, &dev->links.suppliers, c_node) {
-               if (link->flags & DL_FLAG_STATELESS)
+               if (!(link->flags & DL_FLAG_MANAGED))
                        continue;
 
                WARN_ON(link->status != DL_STATE_CONSUMER_PROBE);
@@ -605,6 +702,13 @@ void device_links_driver_bound(struct device *dev)
        device_links_write_unlock();
 }
 
+static void device_link_drop_managed(struct device_link *link)
+{
+       link->flags &= ~DL_FLAG_MANAGED;
+       WRITE_ONCE(link->status, DL_STATE_NONE);
+       kref_put(&link->kref, __device_link_del);
+}
+
 /**
  * __device_links_no_driver - Update links of a device without a driver.
  * @dev: Device without a drvier.
@@ -615,18 +719,18 @@ void device_links_driver_bound(struct device *dev)
  * unless they already are in the "supplier unbind in progress" state in which
  * case they need not be updated.
  *
- * Links with the DL_FLAG_STATELESS flag set are ignored.
+ * Links without the DL_FLAG_MANAGED flag set are ignored.
  */
 static void __device_links_no_driver(struct device *dev)
 {
        struct device_link *link, *ln;
 
        list_for_each_entry_safe_reverse(link, ln, &dev->links.suppliers, c_node) {
-               if (link->flags & DL_FLAG_STATELESS)
+               if (!(link->flags & DL_FLAG_MANAGED))
                        continue;
 
                if (link->flags & DL_FLAG_AUTOREMOVE_CONSUMER)
-                       __device_link_del(&link->kref);
+                       device_link_drop_managed(link);
                else if (link->status == DL_STATE_CONSUMER_PROBE ||
                         link->status == DL_STATE_ACTIVE)
                        WRITE_ONCE(link->status, DL_STATE_AVAILABLE);
@@ -643,7 +747,7 @@ static void __device_links_no_driver(struct device *dev)
  * %__device_links_no_driver() to update links to suppliers for it as
  * appropriate.
  *
- * Links with the DL_FLAG_STATELESS flag set are ignored.
+ * Links without the DL_FLAG_MANAGED flag set are ignored.
  */
 void device_links_no_driver(struct device *dev)
 {
@@ -652,7 +756,7 @@ void device_links_no_driver(struct device *dev)
        device_links_write_lock();
 
        list_for_each_entry(link, &dev->links.consumers, s_node) {
-               if (link->flags & DL_FLAG_STATELESS)
+               if (!(link->flags & DL_FLAG_MANAGED))
                        continue;
 
                /*
@@ -680,7 +784,7 @@ void device_links_no_driver(struct device *dev)
  * invoke %__device_links_no_driver() to update links to suppliers for it as
  * appropriate.
  *
- * Links with the DL_FLAG_STATELESS flag set are ignored.
+ * Links without the DL_FLAG_MANAGED flag set are ignored.
  */
 void device_links_driver_cleanup(struct device *dev)
 {
@@ -689,7 +793,7 @@ void device_links_driver_cleanup(struct device *dev)
        device_links_write_lock();
 
        list_for_each_entry_safe(link, ln, &dev->links.consumers, s_node) {
-               if (link->flags & DL_FLAG_STATELESS)
+               if (!(link->flags & DL_FLAG_MANAGED))
                        continue;
 
                WARN_ON(link->flags & DL_FLAG_AUTOREMOVE_CONSUMER);
@@ -702,7 +806,7 @@ void device_links_driver_cleanup(struct device *dev)
                 */
                if (link->status == DL_STATE_SUPPLIER_UNBIND &&
                    link->flags & DL_FLAG_AUTOREMOVE_SUPPLIER)
-                       __device_link_del(&link->kref);
+                       device_link_drop_managed(link);
 
                WRITE_ONCE(link->status, DL_STATE_DORMANT);
        }
@@ -724,7 +828,7 @@ void device_links_driver_cleanup(struct device *dev)
  *
  * Return 'false' if there are no probing or active consumers.
  *
- * Links with the DL_FLAG_STATELESS flag set are ignored.
+ * Links without the DL_FLAG_MANAGED flag set are ignored.
  */
 bool device_links_busy(struct device *dev)
 {
@@ -734,7 +838,7 @@ bool device_links_busy(struct device *dev)
        device_links_write_lock();
 
        list_for_each_entry(link, &dev->links.consumers, s_node) {
-               if (link->flags & DL_FLAG_STATELESS)
+               if (!(link->flags & DL_FLAG_MANAGED))
                        continue;
 
                if (link->status == DL_STATE_CONSUMER_PROBE
@@ -764,7 +868,7 @@ bool device_links_busy(struct device *dev)
  * driver to unbind and start over (the consumer will not re-probe as we have
  * changed the state of the link already).
  *
- * Links with the DL_FLAG_STATELESS flag set are ignored.
+ * Links without the DL_FLAG_MANAGED flag set are ignored.
  */
 void device_links_unbind_consumers(struct device *dev)
 {
@@ -776,7 +880,7 @@ void device_links_unbind_consumers(struct device *dev)
        list_for_each_entry(link, &dev->links.consumers, s_node) {
                enum device_link_state status;
 
-               if (link->flags & DL_FLAG_STATELESS)
+               if (!(link->flags & DL_FLAG_MANAGED))
                        continue;
 
                status = link->status;
@@ -812,6 +916,10 @@ static void device_links_purge(struct device *dev)
 {
        struct device_link *link, *ln;
 
+       mutex_lock(&wfs_lock);
+       list_del(&dev->links.needs_suppliers);
+       mutex_unlock(&wfs_lock);
+
        /*
         * Delete all of the remaining links from this device to any other
         * devices (either consumers or suppliers).
@@ -1676,6 +1784,7 @@ void device_initialize(struct device *dev)
 #endif
        INIT_LIST_HEAD(&dev->links.consumers);
        INIT_LIST_HEAD(&dev->links.suppliers);
+       INIT_LIST_HEAD(&dev->links.needs_suppliers);
        dev->links.status = DL_DEV_NO_DRIVER;
 }
 EXPORT_SYMBOL_GPL(device_initialize);
@@ -1823,12 +1932,63 @@ static inline struct kobject *get_glue_dir(struct device *dev)
  */
 static void cleanup_glue_dir(struct device *dev, struct kobject *glue_dir)
 {
+       unsigned int ref;
+
        /* see if we live in a "glue" directory */
        if (!live_in_glue_dir(glue_dir, dev))
                return;
 
        mutex_lock(&gdp_mutex);
-       if (!kobject_has_children(glue_dir))
+       /**
+        * There is a race condition between removing glue directory
+        * and adding a new device under the glue directory.
+        *
+        * CPU1:                                         CPU2:
+        *
+        * device_add()
+        *   get_device_parent()
+        *     class_dir_create_and_add()
+        *       kobject_add_internal()
+        *         create_dir()    // create glue_dir
+        *
+        *                                               device_add()
+        *                                                 get_device_parent()
+        *                                                   kobject_get() // get glue_dir
+        *
+        * device_del()
+        *   cleanup_glue_dir()
+        *     kobject_del(glue_dir)
+        *
+        *                                               kobject_add()
+        *                                                 kobject_add_internal()
+        *                                                   create_dir() // in glue_dir
+        *                                                     sysfs_create_dir_ns()
+        *                                                       kernfs_create_dir_ns(sd)
+        *
+        *       sysfs_remove_dir() // glue_dir->sd=NULL
+        *       sysfs_put()        // free glue_dir->sd
+        *
+        *                                                         // sd is freed
+        *                                                         kernfs_new_node(sd)
+        *                                                           kernfs_get(glue_dir)
+        *                                                           kernfs_add_one()
+        *                                                           kernfs_put()
+        *
+        * Before CPU1 remove last child device under glue dir, if CPU2 add
+        * a new device under glue dir, the glue_dir kobject reference count
+        * will be increase to 2 in kobject_get(k). And CPU2 has been called
+        * kernfs_create_dir_ns(). Meanwhile, CPU1 call sysfs_remove_dir()
+        * and sysfs_put(). This result in glue_dir->sd is freed.
+        *
+        * Then the CPU2 will see a stale "empty" but still potentially used
+        * glue dir around in kernfs_new_node().
+        *
+        * In order to avoid this happening, we also should make sure that
+        * kernfs_node for glue_dir is released in CPU1 only when refcount
+        * for glue_dir kobj is 1.
+        */
+       ref = kref_read(&glue_dir->kref);
+       if (!kobject_has_children(glue_dir) && !--ref)
                kobject_del(glue_dir);
        kobject_put(glue_dir);
        mutex_unlock(&gdp_mutex);
@@ -2111,6 +2271,24 @@ int device_add(struct device *dev)
                                             BUS_NOTIFY_ADD_DEVICE, dev);
 
        kobject_uevent(&dev->kobj, KOBJ_ADD);
+
+       /*
+        * Check if any of the other devices (consumers) have been waiting for
+        * this device (supplier) to be added so that they can create a device
+        * link to it.
+        *
+        * This needs to happen after device_pm_add() because device_link_add()
+        * requires the supplier be registered before it's called.
+        *
+        * But this also needs to happe before bus_probe_device() to make sure
+        * waiting consumers can link to it before the driver is bound to the
+        * device and the driver sync_state callback is called for this device.
+        */
+       device_link_check_waiting_consumers();
+
+       if (dev->bus && dev->bus->add_links && dev->bus->add_links(dev))
+               device_link_wait_for_supplier(dev);
+
        bus_probe_device(dev);
        if (parent)
                klist_add_tail(&dev->p->knode_parent,
@@ -2881,13 +3059,6 @@ struct device *device_create_with_groups(struct class *class,
 }
 EXPORT_SYMBOL_GPL(device_create_with_groups);
 
-static int __match_devt(struct device *dev, const void *data)
-{
-       const dev_t *devt = data;
-
-       return dev->devt == *devt;
-}
-
 /**
  * device_destroy - removes a device that was created with device_create()
  * @class: pointer to the struct class that this device was registered with
@@ -2900,7 +3071,7 @@ void device_destroy(struct class *class, dev_t devt)
 {
        struct device *dev;
 
-       dev = class_find_device(class, NULL, &devt, __match_devt);
+       dev = class_find_device_by_devt(class, devt);
        if (dev) {
                put_device(dev);
                device_unregister(dev);
@@ -3371,8 +3542,38 @@ void device_set_of_node_from_dev(struct device *dev, const struct device *dev2)
 }
 EXPORT_SYMBOL_GPL(device_set_of_node_from_dev);
 
+int device_match_name(struct device *dev, const void *name)
+{
+       return sysfs_streq(dev_name(dev), name);
+}
+EXPORT_SYMBOL_GPL(device_match_name);
+
 int device_match_of_node(struct device *dev, const void *np)
 {
        return dev->of_node == np;
 }
 EXPORT_SYMBOL_GPL(device_match_of_node);
+
+int device_match_fwnode(struct device *dev, const void *fwnode)
+{
+       return dev_fwnode(dev) == fwnode;
+}
+EXPORT_SYMBOL_GPL(device_match_fwnode);
+
+int device_match_devt(struct device *dev, const void *pdevt)
+{
+       return dev->devt == *(dev_t *)pdevt;
+}
+EXPORT_SYMBOL_GPL(device_match_devt);
+
+int device_match_acpi_dev(struct device *dev, const void *adev)
+{
+       return ACPI_COMPANION(dev) == adev;
+}
+EXPORT_SYMBOL(device_match_acpi_dev);
+
+int device_match_any(struct device *dev, const void *unused)
+{
+       return 1;
+}
+EXPORT_SYMBOL_GPL(device_match_any);