Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Linux/drivers/base/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 143 kB image not shown  

Quelle  core.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
/*
 * drivers/base/core.c - core driver model code (device registration, etc)
 *
 * Copyright (c) 2002-3 Patrick Mochel
 * Copyright (c) 2002-3 Open Source Development Labs
 * Copyright (c) 2006 Greg Kroah-Hartman <gregkh@suse.de>
 * Copyright (c) 2006 Novell, Inc.
 */


#include <linux/acpi.h>
#include <linux/blkdev.h>
#include <linux/cleanup.h>
#include <linux/cpufreq.h>
#include <linux/device.h>
#include <linux/dma-map-ops.h> /* for dma_default_coherent */
#include <linux/err.h>
#include <linux/fwnode.h>
#include <linux/init.h>
#include <linux/kdev_t.h>
#include <linux/kstrtox.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/netdevice.h>
#include <linux/notifier.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/pm_runtime.h>
#include <linux/sched/mm.h>
#include <linux/sched/signal.h>
#include <linux/slab.h>
#include <linux/string_helpers.h>
#include <linux/swiotlb.h>
#include <linux/sysfs.h>

#include "base.h"
#include "physical_location.h"
#include "power/power.h"

/* Device links support. */
static LIST_HEAD(deferred_sync);
static unsigned int defer_sync_state_count = 1;
static DEFINE_MUTEX(fwnode_link_lock);
static bool fw_devlink_is_permissive(void);
static void __fw_devlink_link_to_consumers(struct device *dev);
static bool fw_devlink_drv_reg_done;
static bool fw_devlink_best_effort;
static struct workqueue_struct *device_link_wq;

/**
 * __fwnode_link_add - Create a link between two fwnode_handles.
 * @con: Consumer end of the link.
 * @sup: Supplier end of the link.
 * @flags: Link flags.
 *
 * Create a fwnode link between fwnode handles @con and @sup. The fwnode link
 * represents the detail that the firmware lists @sup fwnode as supplying a
 * resource to @con.
 *
 * The driver core will use the fwnode link to create a device link between the
 * two device objects corresponding to @con and @sup when they are created. The
 * driver core will automatically delete the fwnode link between @con and @sup
 * after doing that.
 *
 * Attempts to create duplicate links between the same pair of fwnode handles
 * are ignored and there is no reference counting.
 */

static int __fwnode_link_add(struct fwnode_handle *con,
        struct fwnode_handle *sup, u8 flags)
{
 struct fwnode_link *link;

 list_for_each_entry(link, &sup->consumers, s_hook)
  if (link->consumer == con) {
   link->flags |= flags;
   return 0;
  }

 link = kzalloc(sizeof(*link), GFP_KERNEL);
 if (!link)
  return -ENOMEM;

 link->supplier = sup;
 INIT_LIST_HEAD(&link->s_hook);
 link->consumer = con;
 INIT_LIST_HEAD(&link->c_hook);
 link->flags = flags;

 list_add(&link->s_hook, &sup->consumers);
 list_add(&link->c_hook, &con->suppliers);
 pr_debug("%pfwf Linked as a fwnode consumer to %pfwf\n",
   con, sup);

 return 0;
}

int fwnode_link_add(struct fwnode_handle *con, struct fwnode_handle *sup,
      u8 flags)
{
 guard(mutex)(&fwnode_link_lock);

 return __fwnode_link_add(con, sup, flags);
}

/**
 * __fwnode_link_del - Delete a link between two fwnode_handles.
 * @link: the fwnode_link to be deleted
 *
 * The fwnode_link_lock needs to be held when this function is called.
 */

static void __fwnode_link_del(struct fwnode_link *link)
{
 pr_debug("%pfwf Dropping the fwnode link to %pfwf\n",
   link->consumer, link->supplier);
 list_del(&link->s_hook);
 list_del(&link->c_hook);
 kfree(link);
}

/**
 * __fwnode_link_cycle - Mark a fwnode link as being part of a cycle.
 * @link: the fwnode_link to be marked
 *
 * The fwnode_link_lock needs to be held when this function is called.
 */

static void __fwnode_link_cycle(struct fwnode_link *link)
{
 pr_debug("%pfwf: cycle: depends on %pfwf\n",
   link->consumer, link->supplier);
 link->flags |= FWLINK_FLAG_CYCLE;
}

/**
 * fwnode_links_purge_suppliers - Delete all supplier links of fwnode_handle.
 * @fwnode: fwnode whose supplier links need to be deleted
 *
 * Deletes all supplier links connecting directly to @fwnode.
 */

static void fwnode_links_purge_suppliers(struct fwnode_handle *fwnode)
{
 struct fwnode_link *link, *tmp;

 guard(mutex)(&fwnode_link_lock);

 list_for_each_entry_safe(link, tmp, &fwnode->suppliers, c_hook)
  __fwnode_link_del(link);
}

/**
 * fwnode_links_purge_consumers - Delete all consumer links of fwnode_handle.
 * @fwnode: fwnode whose consumer links need to be deleted
 *
 * Deletes all consumer links connecting directly to @fwnode.
 */

static void fwnode_links_purge_consumers(struct fwnode_handle *fwnode)
{
 struct fwnode_link *link, *tmp;

 guard(mutex)(&fwnode_link_lock);

 list_for_each_entry_safe(link, tmp, &fwnode->consumers, s_hook)
  __fwnode_link_del(link);
}

/**
 * fwnode_links_purge - Delete all links connected to a fwnode_handle.
 * @fwnode: fwnode whose links needs to be deleted
 *
 * Deletes all links connecting directly to a fwnode.
 */

void fwnode_links_purge(struct fwnode_handle *fwnode)
{
 fwnode_links_purge_suppliers(fwnode);
 fwnode_links_purge_consumers(fwnode);
}

void fw_devlink_purge_absent_suppliers(struct fwnode_handle *fwnode)
{
 struct fwnode_handle *child;

 /* Don't purge consumer links of an added child */
 if (fwnode->dev)
  return;

 fwnode->flags |= FWNODE_FLAG_NOT_DEVICE;
 fwnode_links_purge_consumers(fwnode);

 fwnode_for_each_available_child_node(fwnode, child)
  fw_devlink_purge_absent_suppliers(child);
}
EXPORT_SYMBOL_GPL(fw_devlink_purge_absent_suppliers);

/**
 * __fwnode_links_move_consumers - Move consumer from @from to @to fwnode_handle
 * @from: move consumers away from this fwnode
 * @to: move consumers to this fwnode
 *
 * Move all consumer links from @from fwnode to @to fwnode.
 */

static void __fwnode_links_move_consumers(struct fwnode_handle *from,
       struct fwnode_handle *to)
{
 struct fwnode_link *link, *tmp;

 list_for_each_entry_safe(link, tmp, &from->consumers, s_hook) {
  __fwnode_link_add(link->consumer, to, link->flags);
  __fwnode_link_del(link);
 }
}

/**
 * __fw_devlink_pickup_dangling_consumers - Pick up dangling consumers
 * @fwnode: fwnode from which to pick up dangling consumers
 * @new_sup: fwnode of new supplier
 *
 * If the @fwnode has a corresponding struct device and the device supports
 * probing (that is, added to a bus), then we want to let fw_devlink create
 * MANAGED device links to this device, so leave @fwnode and its descendant's
 * fwnode links alone.
 *
 * Otherwise, move its consumers to the new supplier @new_sup.
 */

static void __fw_devlink_pickup_dangling_consumers(struct fwnode_handle *fwnode,
         struct fwnode_handle *new_sup)
{
 struct fwnode_handle *child;

 if (fwnode->dev && fwnode->dev->bus)
  return;

 fwnode->flags |= FWNODE_FLAG_NOT_DEVICE;
 __fwnode_links_move_consumers(fwnode, new_sup);

 fwnode_for_each_available_child_node(fwnode, child)
  __fw_devlink_pickup_dangling_consumers(child, new_sup);
}

static DEFINE_MUTEX(device_links_lock);
DEFINE_STATIC_SRCU(device_links_srcu);

static inline void device_links_write_lock(void)
{
 mutex_lock(&device_links_lock);
}

static inline void device_links_write_unlock(void)
{
 mutex_unlock(&device_links_lock);
}

int device_links_read_lock(void) __acquires(&device_links_srcu)
{
 return srcu_read_lock(&device_links_srcu);
}

void device_links_read_unlock(int idx) __releases(&device_links_srcu)
{
 srcu_read_unlock(&device_links_srcu, idx);
}

int device_links_read_lock_held(void)
{
 return srcu_read_lock_held(&device_links_srcu);
}

static void device_link_synchronize_removal(void)
{
 synchronize_srcu(&device_links_srcu);
}

static void device_link_remove_from_lists(struct device_link *link)
{
 list_del_rcu(&link->s_node);
 list_del_rcu(&link->c_node);
}

static bool device_is_ancestor(struct device *dev, struct device *target)
{
 while (target->parent) {
  target = target->parent;
  if (dev == target)
   return true;
 }
 return false;
}

#define DL_MARKER_FLAGS  (DL_FLAG_INFERRED | \
     DL_FLAG_CYCLE | \
     DL_FLAG_MANAGED)
bool device_link_flag_is_sync_state_only(u32 flags)
{
 return (flags & ~DL_MARKER_FLAGS) == DL_FLAG_SYNC_STATE_ONLY;
}

/**
 * device_is_dependent - Check if one device depends on another one
 * @dev: Device to check dependencies for.
 * @target: Device to check against.
 *
 * Check if @target depends on @dev or any device dependent on it (its child or
 * its consumer etc).  Return 1 if that is the case or 0 otherwise.
 */

static int device_is_dependent(struct device *dev, void *target)
{
 struct device_link *link;
 int ret;

 /*
 * The "ancestors" check is needed to catch the case when the target
 * device has not been completely initialized yet and it is still
 * missing from the list of children of its parent device.
 */

 if (dev == target || device_is_ancestor(dev, target))
  return 1;

 ret = device_for_each_child(dev, target, device_is_dependent);
 if (ret)
  return ret;

 list_for_each_entry(link, &dev->links.consumers, s_node) {
  if (device_link_flag_is_sync_state_only(link->flags))
   continue;

  if (link->consumer == target)
   return 1;

  ret = device_is_dependent(link->consumer, target);
  if (ret)
   break;
 }
 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;

 /*
 * Devices that have not been registered yet will be put to the ends
 * of the lists during the registration, so skip them here.
 */

 if (device_is_registered(dev))
  devices_kset_move_last(dev);

 if (device_pm_initialized(dev))
  device_pm_move_last(dev);

 device_for_each_child(dev, NULL, device_reorder_to_tail);
 list_for_each_entry(link, &dev->links.consumers, s_node) {
  if (device_link_flag_is_sync_state_only(link->flags))
   continue;
  device_reorder_to_tail(link->consumer, NULL);
 }

 return 0;
}

/**
 * device_pm_move_to_tail - Move set of devices to the end of device lists
 * @dev: Device to move
 *
 * This is a device_reorder_to_tail() wrapper taking the requisite locks.
 *
 * It moves the @dev along with all of its children and all of its consumers
 * to the ends of the device_kset and dpm_list, recursively.
 */

void device_pm_move_to_tail(struct device *dev)
{
 int idx;

 idx = device_links_read_lock();
 device_pm_lock();
 device_reorder_to_tail(dev, NULL);
 device_pm_unlock();
 device_links_read_unlock(idx);
}

#define to_devlink(dev) container_of((dev), struct device_link, link_dev)

static ssize_t status_show(struct device *dev,
      struct device_attribute *attr, char *buf)
{
 const char *output;

 switch (to_devlink(dev)->status) {
 case DL_STATE_NONE:
  output = "not tracked";
  break;
 case DL_STATE_DORMANT:
  output = "dormant";
  break;
 case DL_STATE_AVAILABLE:
  output = "available";
  break;
 case DL_STATE_CONSUMER_PROBE:
  output = "consumer probing";
  break;
 case DL_STATE_ACTIVE:
  output = "active";
  break;
 case DL_STATE_SUPPLIER_UNBIND:
  output = "supplier unbinding";
  break;
 default:
  output = "unknown";
  break;
 }

 return sysfs_emit(buf, "%s\n", output);
}
static DEVICE_ATTR_RO(status);

static ssize_t auto_remove_on_show(struct device *dev,
       struct device_attribute *attr, char *buf)
{
 struct device_link *link = to_devlink(dev);
 const char *output;

 if (device_link_test(link, DL_FLAG_AUTOREMOVE_SUPPLIER))
  output = "supplier unbind";
 else if (device_link_test(link, DL_FLAG_AUTOREMOVE_CONSUMER))
  output = "consumer unbind";
 else
  output = "never";

 return sysfs_emit(buf, "%s\n", output);
}
static DEVICE_ATTR_RO(auto_remove_on);

static ssize_t runtime_pm_show(struct device *dev,
          struct device_attribute *attr, char *buf)
{
 struct device_link *link = to_devlink(dev);

 return sysfs_emit(buf, "%d\n", device_link_test(link, DL_FLAG_PM_RUNTIME));
}
static DEVICE_ATTR_RO(runtime_pm);

static ssize_t sync_state_only_show(struct device *dev,
        struct device_attribute *attr, char *buf)
{
 struct device_link *link = to_devlink(dev);

 return sysfs_emit(buf, "%d\n", device_link_test(link, DL_FLAG_SYNC_STATE_ONLY));
}
static DEVICE_ATTR_RO(sync_state_only);

static struct attribute *devlink_attrs[] = {
 &dev_attr_status.attr,
 &dev_attr_auto_remove_on.attr,
 &dev_attr_runtime_pm.attr,
 &dev_attr_sync_state_only.attr,
 NULL,
};
ATTRIBUTE_GROUPS(devlink);

static void device_link_release_fn(struct work_struct *work)
{
 struct device_link *link = container_of(work, struct device_link, rm_work);

 /* Ensure that all references to the link object have been dropped. */
 device_link_synchronize_removal();

 pm_runtime_release_supplier(link);
 /*
 * If supplier_preactivated is set, the link has been dropped between
 * the pm_runtime_get_suppliers() and pm_runtime_put_suppliers() calls
 * in __driver_probe_device().  In that case, drop the supplier's
 * PM-runtime usage counter to remove the reference taken by
 * pm_runtime_get_suppliers().
 */

 if (link->supplier_preactivated)
  pm_runtime_put_noidle(link->supplier);

 pm_request_idle(link->supplier);

 put_device(link->consumer);
 put_device(link->supplier);
 kfree(link);
}

static void devlink_dev_release(struct device *dev)
{
 struct device_link *link = to_devlink(dev);

 INIT_WORK(&link->rm_work, device_link_release_fn);
 /*
 * It may take a while to complete this work because of the SRCU
 * synchronization in device_link_release_fn() and if the consumer or
 * supplier devices get deleted when it runs, so put it into the
 * dedicated workqueue.
 */

 queue_work(device_link_wq, &link->rm_work);
}

/**
 * device_link_wait_removal - Wait for ongoing devlink removal jobs to terminate
 */

void device_link_wait_removal(void)
{
 /*
 * devlink removal jobs are queued in the dedicated work queue.
 * To be sure that all removal jobs are terminated, ensure that any
 * scheduled work has run to completion.
 */

 flush_workqueue(device_link_wq);
}
EXPORT_SYMBOL_GPL(device_link_wait_removal);

static const struct class devlink_class = {
 .name = "devlink",
 .dev_groups = devlink_groups,
 .dev_release = devlink_dev_release,
};

static int devlink_add_symlinks(struct device *dev)
{
 char *buf_con __free(kfree) = NULL, *buf_sup __free(kfree) = NULL;
 int ret;
 struct device_link *link = to_devlink(dev);
 struct device *sup = link->supplier;
 struct device *con = link->consumer;

 ret = sysfs_create_link(&link->link_dev.kobj, &sup->kobj, "supplier");
 if (ret)
  goto out;

 ret = sysfs_create_link(&link->link_dev.kobj, &con->kobj, "consumer");
 if (ret)
  goto err_con;

 buf_con = kasprintf(GFP_KERNEL, "consumer:%s:%s", dev_bus_name(con), dev_name(con));
 if (!buf_con) {
  ret = -ENOMEM;
  goto err_con_dev;
 }

 ret = sysfs_create_link(&sup->kobj, &link->link_dev.kobj, buf_con);
 if (ret)
  goto err_con_dev;

 buf_sup = kasprintf(GFP_KERNEL, "supplier:%s:%s", dev_bus_name(sup), dev_name(sup));
 if (!buf_sup) {
  ret = -ENOMEM;
  goto err_sup_dev;
 }

 ret = sysfs_create_link(&con->kobj, &link->link_dev.kobj, buf_sup);
 if (ret)
  goto err_sup_dev;

 goto out;

err_sup_dev:
 sysfs_remove_link(&sup->kobj, buf_con);
err_con_dev:
 sysfs_remove_link(&link->link_dev.kobj, "consumer");
err_con:
 sysfs_remove_link(&link->link_dev.kobj, "supplier");
out:
 return ret;
}

static void devlink_remove_symlinks(struct device *dev)
{
 char *buf_con __free(kfree) = NULL, *buf_sup __free(kfree) = NULL;
 struct device_link *link = to_devlink(dev);
 struct device *sup = link->supplier;
 struct device *con = link->consumer;

 sysfs_remove_link(&link->link_dev.kobj, "consumer");
 sysfs_remove_link(&link->link_dev.kobj, "supplier");

 if (device_is_registered(con)) {
  buf_sup = kasprintf(GFP_KERNEL, "supplier:%s:%s", dev_bus_name(sup), dev_name(sup));
  if (!buf_sup)
   goto out;
  sysfs_remove_link(&con->kobj, buf_sup);
 }

 buf_con = kasprintf(GFP_KERNEL, "consumer:%s:%s", dev_bus_name(con), dev_name(con));
 if (!buf_con)
  goto out;
 sysfs_remove_link(&sup->kobj, buf_con);

 return;

out:
 WARN(1, "Unable to properly free device link symlinks!\n");
}

static struct class_interface devlink_class_intf = {
 .class = &devlink_class,
 .add_dev = devlink_add_symlinks,
 .remove_dev = devlink_remove_symlinks,
};

static int __init devlink_class_init(void)
{
 int ret;

 ret = class_register(&devlink_class);
 if (ret)
  return ret;

 ret = class_interface_register(&devlink_class_intf);
 if (ret)
  class_unregister(&devlink_class);

 return ret;
}
postcore_initcall(devlink_class_init);

#define DL_MANAGED_LINK_FLAGS (DL_FLAG_AUTOREMOVE_CONSUMER | \
          DL_FLAG_AUTOREMOVE_SUPPLIER | \
          DL_FLAG_AUTOPROBE_CONSUMER  | \
          DL_FLAG_SYNC_STATE_ONLY | \
          DL_FLAG_INFERRED | \
          DL_FLAG_CYCLE)

#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.
 * @supplier: Supplier end of the link.
 * @flags: Link flags.
 *
 * Return: On success, a device_link struct will be returned.
 *         On error or invalid flag settings, NULL will be returned.
 *
 * The caller is responsible for the proper synchronization of the link creation
 * with runtime PM.  First, setting the DL_FLAG_PM_RUNTIME flag will cause the
 * runtime PM framework to take the link into account.  Second, if the
 * DL_FLAG_RPM_ACTIVE flag is set in addition to it, the supplier devices will
 * be forced into the active meta state and reference-counted upon the creation
 * 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 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
 * can only be used to check whether or not the link is present.  In that case,
 * the DL_FLAG_AUTOREMOVE_CONSUMER and DL_FLAG_AUTOREMOVE_SUPPLIER device link
 * flags can be used to indicate to the driver core when the link can be safely
 * deleted.  Namely, setting one of them in @flags indicates to the driver core
 * that the link is not going to be used (by the given caller of this function)
 * after unbinding the consumer or supplier driver, respectively, from its
 * device, so the link can be deleted at that point.  If none of them is set,
 * the link will be maintained until one of the devices pointed to by it (either
 * the consumer or the supplier) is unregistered.
 *
 * Also, if DL_FLAG_STATELESS, DL_FLAG_AUTOREMOVE_CONSUMER and
 * DL_FLAG_AUTOREMOVE_SUPPLIER are not set in @flags (that is, a persistent
 * managed device link is being added), the DL_FLAG_AUTOPROBE_CONSUMER flag can
 * be used to request the driver core to automatically probe for a consumer
 * driver after successfully binding a driver to the supplier device.
 *
 * 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
 * on it to the ends of these lists (that does not happen to devices that have
 * not been registered when this function is called).
 *
 * The supplier device is required to be registered when this function is called
 * and NULL will be returned if that is not the case.  The consumer device need
 * not be registered, however.
 */

struct device_link *device_link_add(struct device *consumer,
        struct device *supplier, u32 flags)
{
 struct device_link *link;

 if (!consumer || !supplier || 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)))
  return NULL;

 if (flags & DL_FLAG_PM_RUNTIME && flags & DL_FLAG_RPM_ACTIVE) {
  if (pm_runtime_get_sync(supplier) < 0) {
   pm_runtime_put_noidle(supplier);
   return NULL;
  }
 }

 if (!(flags & DL_FLAG_STATELESS))
  flags |= DL_FLAG_MANAGED;

 if (flags & DL_FLAG_SYNC_STATE_ONLY &&
     !device_link_flag_is_sync_state_only(flags))
  return NULL;

 device_links_write_lock();
 device_pm_lock();

 /*
 * If the supplier has not been fully registered yet or there is a
 * reverse (non-SYNC_STATE_ONLY) dependency between the consumer and
 * the supplier already in the graph, return NULL. If the link is a
 * SYNC_STATE_ONLY link, we don't check for reverse dependencies
 * because it only affects sync_state() callbacks.
 */

 if (!device_pm_initialized(supplier)
     || (!(flags & DL_FLAG_SYNC_STATE_ONLY) &&
    device_is_dependent(consumer, supplier))) {
  link = NULL;
  goto out;
 }

 /*
 * SYNC_STATE_ONLY links are useless once a consumer device has probed.
 * So, only create it if the consumer hasn't probed yet.
 */

 if (flags & DL_FLAG_SYNC_STATE_ONLY &&
     consumer->links.status != DL_DEV_NO_DRIVER &&
     consumer->links.status != DL_DEV_PROBING) {
  link = NULL;
  goto out;
 }

 /*
 * DL_FLAG_AUTOREMOVE_SUPPLIER indicates that the link will be needed
 * longer than for DL_FLAG_AUTOREMOVE_CONSUMER and setting them both
 * together doesn't make sense, so prefer DL_FLAG_AUTOREMOVE_SUPPLIER.
 */

 if (flags & DL_FLAG_AUTOREMOVE_SUPPLIER)
  flags &= ~DL_FLAG_AUTOREMOVE_CONSUMER;

 list_for_each_entry(link, &supplier->links.consumers, s_node) {
  if (link->consumer != consumer)
   continue;

  if (device_link_test(link, DL_FLAG_INFERRED) &&
      !(flags & DL_FLAG_INFERRED))
   link->flags &= ~DL_FLAG_INFERRED;

  if (flags & DL_FLAG_PM_RUNTIME) {
   if (!device_link_test(link, DL_FLAG_PM_RUNTIME)) {
    pm_runtime_new_link(consumer);
    link->flags |= DL_FLAG_PM_RUNTIME;
   }
   if (flags & DL_FLAG_RPM_ACTIVE)
    refcount_inc(&link->rpm_active);
  }

  if (flags & DL_FLAG_STATELESS) {
   kref_get(&link->kref);
   if (device_link_test(link, DL_FLAG_SYNC_STATE_ONLY) &&
       !device_link_test(link, DL_FLAG_STATELESS)) {
    link->flags |= DL_FLAG_STATELESS;
    goto reorder;
   } else {
    link->flags |= DL_FLAG_STATELESS;
    goto out;
   }
  }

  /*
 * If the life time of the link following from the new flags is
 * longer than indicated by the flags of the existing link,
 * update the existing link to stay around longer.
 */

  if (flags & DL_FLAG_AUTOREMOVE_SUPPLIER) {
   if (device_link_test(link, DL_FLAG_AUTOREMOVE_CONSUMER)) {
    link->flags &= ~DL_FLAG_AUTOREMOVE_CONSUMER;
    link->flags |= DL_FLAG_AUTOREMOVE_SUPPLIER;
   }
  } else if (!(flags & DL_FLAG_AUTOREMOVE_CONSUMER)) {
   link->flags &= ~(DL_FLAG_AUTOREMOVE_CONSUMER |
      DL_FLAG_AUTOREMOVE_SUPPLIER);
  }
  if (!device_link_test(link, DL_FLAG_MANAGED)) {
   kref_get(&link->kref);
   link->flags |= DL_FLAG_MANAGED;
   device_link_init_status(link, consumer, supplier);
  }
  if (device_link_test(link, DL_FLAG_SYNC_STATE_ONLY) &&
      !(flags & DL_FLAG_SYNC_STATE_ONLY)) {
   link->flags &= ~DL_FLAG_SYNC_STATE_ONLY;
   goto reorder;
  }

  goto out;
 }

 link = kzalloc(sizeof(*link), GFP_KERNEL);
 if (!link)
  goto out;

 refcount_set(&link->rpm_active, 1);

 get_device(supplier);
 link->supplier = supplier;
 INIT_LIST_HEAD(&link->s_node);
 get_device(consumer);
 link->consumer = consumer;
 INIT_LIST_HEAD(&link->c_node);
 link->flags = flags;
 kref_init(&link->kref);

 link->link_dev.class = &devlink_class;
 device_set_pm_not_required(&link->link_dev);
 dev_set_name(&link->link_dev, "%s:%s--%s:%s",
       dev_bus_name(supplier), dev_name(supplier),
       dev_bus_name(consumer), dev_name(consumer));
 if (device_register(&link->link_dev)) {
  put_device(&link->link_dev);
  link = NULL;
  goto out;
 }

 if (flags & DL_FLAG_PM_RUNTIME) {
  if (flags & DL_FLAG_RPM_ACTIVE)
   refcount_inc(&link->rpm_active);

  pm_runtime_new_link(consumer);
 }

 /* Determine the initial link state. */
 if (flags & DL_FLAG_STATELESS)
  link->status = DL_STATE_NONE;
 else
  device_link_init_status(link, consumer, supplier);

 /*
 * Some callers expect the link creation during consumer driver probe to
 * resume the supplier even without DL_FLAG_RPM_ACTIVE.
 */

 if (link->status == DL_STATE_CONSUMER_PROBE &&
     flags & DL_FLAG_PM_RUNTIME)
  pm_runtime_resume(supplier);

 list_add_tail_rcu(&link->s_node, &supplier->links.consumers);
 list_add_tail_rcu(&link->c_node, &consumer->links.suppliers);

 if (flags & DL_FLAG_SYNC_STATE_ONLY) {
  dev_dbg(consumer,
   "Linked as a sync state only consumer to %s\n",
   dev_name(supplier));
  goto out;
 }

reorder:
 /*
 * Move the consumer and all of the devices depending on it to the end
 * of dpm_list and the devices_kset list.
 *
 * It is necessary to hold dpm_list locked throughout all that or else
 * we may end up suspending with a wrong ordering of it.
 */

 device_reorder_to_tail(consumer, NULL);

 dev_dbg(consumer, "Linked as a consumer to %s\n", dev_name(supplier));

out:
 device_pm_unlock();
 device_links_write_unlock();

 if ((flags & DL_FLAG_PM_RUNTIME && flags & DL_FLAG_RPM_ACTIVE) && !link)
  pm_runtime_put(supplier);

 return link;
}
EXPORT_SYMBOL_GPL(device_link_add);

static void __device_link_del(struct kref *kref)
{
 struct device_link *link = container_of(kref, struct device_link, kref);

 dev_dbg(link->consumer, "Dropping the link to %s\n",
  dev_name(link->supplier));

 pm_runtime_drop_link(link);

 device_link_remove_from_lists(link);
 device_unregister(&link->link_dev);
}

static void device_link_put_kref(struct device_link *link)
{
 if (device_link_test(link, DL_FLAG_STATELESS))
  kref_put(&link->kref, __device_link_del);
 else if (!device_is_registered(link->consumer))
  __device_link_del(&link->kref);
 else
  WARN(1, "Unable to drop a managed device link reference\n");
}

/**
 * device_link_del - Delete a stateless link between two devices.
 * @link: Device link to delete.
 *
 * The caller must ensure proper synchronization of this function with runtime
 * PM.  If the link was added multiple times, it needs to be deleted as often.
 * Care is required for hotplugged devices:  Their links are purged on removal
 * and calling device_link_del() is then no longer allowed.
 */

void device_link_del(struct device_link *link)
{
 device_links_write_lock();
 device_link_put_kref(link);
 device_links_write_unlock();
}
EXPORT_SYMBOL_GPL(device_link_del);

/**
 * device_link_remove - Delete a stateless link between two devices.
 * @consumer: Consumer end of the link.
 * @supplier: Supplier end of the link.
 *
 * The caller must ensure proper synchronization of this function with runtime
 * PM.
 */

void device_link_remove(void *consumer, struct device *supplier)
{
 struct device_link *link;

 if (WARN_ON(consumer == supplier))
  return;

 device_links_write_lock();

 list_for_each_entry(link, &supplier->links.consumers, s_node) {
  if (link->consumer == consumer) {
   device_link_put_kref(link);
   break;
  }
 }

 device_links_write_unlock();
}
EXPORT_SYMBOL_GPL(device_link_remove);

static void device_links_missing_supplier(struct device *dev)
{
 struct device_link *link;

 list_for_each_entry(link, &dev->links.suppliers, c_node) {
  if (link->status != DL_STATE_CONSUMER_PROBE)
   continue;

  if (link->supplier->links.status == DL_DEV_DRIVER_BOUND) {
   WRITE_ONCE(link->status, DL_STATE_AVAILABLE);
  } else {
   WARN_ON(!device_link_test(link, DL_FLAG_SYNC_STATE_ONLY));
   WRITE_ONCE(link->status, DL_STATE_DORMANT);
  }
 }
}

static bool dev_is_best_effort(struct device *dev)
{
 return (fw_devlink_best_effort && dev->can_match) ||
  (dev->fwnode && (dev->fwnode->flags & FWNODE_FLAG_BEST_EFFORT));
}

static struct fwnode_handle *fwnode_links_check_suppliers(
      struct fwnode_handle *fwnode)
{
 struct fwnode_link *link;

 if (!fwnode || fw_devlink_is_permissive())
  return NULL;

 list_for_each_entry(link, &fwnode->suppliers, c_hook)
  if (!(link->flags &
        (FWLINK_FLAG_CYCLE | FWLINK_FLAG_IGNORE)))
   return link->supplier;

 return NULL;
}

/**
 * device_links_check_suppliers - Check presence of supplier drivers.
 * @dev: Consumer device.
 *
 * Check links from this device to any suppliers.  Walk the list of the device's
 * links to suppliers and see if all of them are available.  If not, simply
 * return -EPROBE_DEFER.
 *
 * We need to guarantee that the supplier will not go away after the check has
 * been positive here.  It only can go away in __device_release_driver() and
 * that function  checks the device's links to consumers.  This means we need to
 * mark the link as "consumer probe in progress" to make the supplier removal
 * wait for us to complete (or bad things may happen).
 *
 * 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, fwnode_ret = 0;
 struct fwnode_handle *sup_fw;

 /*
 * Device waiting for supplier to become available is not allowed to
 * probe.
 */

 scoped_guard(mutex, &fwnode_link_lock) {
  sup_fw = fwnode_links_check_suppliers(dev->fwnode);
  if (sup_fw) {
   if (dev_is_best_effort(dev))
    fwnode_ret = -EAGAIN;
   else
    return dev_err_probe(dev, -EPROBE_DEFER,
           "wait for supplier %pfwf\n", sup_fw);
  }
 }

 device_links_write_lock();

 list_for_each_entry(link, &dev->links.suppliers, c_node) {
  if (!device_link_test(link, DL_FLAG_MANAGED))
   continue;

  if (link->status != DL_STATE_AVAILABLE &&
      !device_link_test(link, DL_FLAG_SYNC_STATE_ONLY)) {

   if (dev_is_best_effort(dev) &&
       device_link_test(link, DL_FLAG_INFERRED) &&
       !link->supplier->can_match) {
    ret = -EAGAIN;
    continue;
   }

   device_links_missing_supplier(dev);
   ret = dev_err_probe(dev, -EPROBE_DEFER,
         "supplier %s not ready\n", dev_name(link->supplier));
   break;
  }
  WRITE_ONCE(link->status, DL_STATE_CONSUMER_PROBE);
 }
 dev->links.status = DL_DEV_PROBING;

 device_links_write_unlock();

 return ret ? ret : fwnode_ret;
}

/**
 * __device_links_queue_sync_state - Queue a device for sync_state() callback
 * @dev: Device to call sync_state() on
 * @list: List head to queue the @dev on
 *
 * Queues a device for a sync_state() callback when the device links write lock
 * isn't held. This allows the sync_state() execution flow to use device links
 * APIs.  The caller must ensure this function is called with
 * device_links_write_lock() held.
 *
 * This function does a get_device() to make sure the device is not freed while
 * on this list.
 *
 * So the caller must also ensure that device_links_flush_sync_list() is called
 * as soon as the caller releases device_links_write_lock().  This is necessary
 * to make sure the sync_state() is called in a timely fashion and the
 * put_device() is called on this device.
 */

static void __device_links_queue_sync_state(struct device *dev,
         struct list_head *list)
{
 struct device_link *link;

 if (!dev_has_sync_state(dev))
  return;
 if (dev->state_synced)
  return;

 list_for_each_entry(link, &dev->links.consumers, s_node) {
  if (!device_link_test(link, DL_FLAG_MANAGED))
   continue;
  if (link->status != DL_STATE_ACTIVE)
   return;
 }

 /*
 * Set the flag here to avoid adding the same device to a list more
 * than once. This can happen if new consumers get added to the device
 * and probed before the list is flushed.
 */

 dev->state_synced = true;

 if (WARN_ON(!list_empty(&dev->links.defer_sync)))
  return;

 get_device(dev);
 list_add_tail(&dev->links.defer_sync, list);
}

/**
 * device_links_flush_sync_list - Call sync_state() on a list of devices
 * @list: List of devices to call sync_state() on
 * @dont_lock_dev: Device for which lock is already held by the caller
 *
 * Calls sync_state() on all the devices that have been queued for it. This
 * function is used in conjunction with __device_links_queue_sync_state(). The
 * @dont_lock_dev parameter is useful when this function is called from a
 * context where a device lock is already held.
 */

static void device_links_flush_sync_list(struct list_head *list,
      struct device *dont_lock_dev)
{
 struct device *dev, *tmp;

 list_for_each_entry_safe(dev, tmp, list, links.defer_sync) {
  list_del_init(&dev->links.defer_sync);

  if (dev != dont_lock_dev)
   device_lock(dev);

  dev_sync_state(dev);

  if (dev != dont_lock_dev)
   device_unlock(dev);

  put_device(dev);
 }
}

void device_links_supplier_sync_state_pause(void)
{
 device_links_write_lock();
 defer_sync_state_count++;
 device_links_write_unlock();
}

void device_links_supplier_sync_state_resume(void)
{
 struct device *dev, *tmp;
 LIST_HEAD(sync_list);

 device_links_write_lock();
 if (!defer_sync_state_count) {
  WARN(true"Unmatched sync_state pause/resume!");
  goto out;
 }
 defer_sync_state_count--;
 if (defer_sync_state_count)
  goto out;

 list_for_each_entry_safe(dev, tmp, &deferred_sync, links.defer_sync) {
  /*
 * Delete from deferred_sync list before queuing it to
 * sync_list because defer_sync is used for both lists.
 */

  list_del_init(&dev->links.defer_sync);
  __device_links_queue_sync_state(dev, &sync_list);
 }
out:
 device_links_write_unlock();

 device_links_flush_sync_list(&sync_list, NULL);
}

static int sync_state_resume_initcall(void)
{
 device_links_supplier_sync_state_resume();
 return 0;
}
late_initcall(sync_state_resume_initcall);

static void __device_links_supplier_defer_sync(struct device *sup)
{
 if (list_empty(&sup->links.defer_sync) && dev_has_sync_state(sup))
  list_add_tail(&sup->links.defer_sync, &deferred_sync);
}

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);
}

static ssize_t waiting_for_supplier_show(struct device *dev,
      struct device_attribute *attr,
      char *buf)
{
 bool val;

 device_lock(dev);
 scoped_guard(mutex, &fwnode_link_lock)
  val = !!fwnode_links_check_suppliers(dev->fwnode);
 device_unlock(dev);
 return sysfs_emit(buf, "%u\n", val);
}
static DEVICE_ATTR_RO(waiting_for_supplier);

/**
 * device_links_force_bind - Prepares device to be force bound
 * @dev: Consumer device.
 *
 * device_bind_driver() force binds a device to a driver without calling any
 * driver probe functions. So the consumer really isn't going to wait for any
 * supplier before it's bound to the driver. We still want the device link
 * states to be sensible when this happens.
 *
 * In preparation for device_bind_driver(), this function goes through each
 * supplier device links and checks if the supplier is bound. If it is, then
 * the device link status is set to CONSUMER_PROBE. Otherwise, the device link
 * is dropped. Links without the DL_FLAG_MANAGED flag set are ignored.
 */

void device_links_force_bind(struct device *dev)
{
 struct device_link *link, *ln;

 device_links_write_lock();

 list_for_each_entry_safe(link, ln, &dev->links.suppliers, c_node) {
  if (!device_link_test(link, DL_FLAG_MANAGED))
   continue;

  if (link->status != DL_STATE_AVAILABLE) {
   device_link_drop_managed(link);
   continue;
  }
  WRITE_ONCE(link->status, DL_STATE_CONSUMER_PROBE);
 }
 dev->links.status = DL_DEV_PROBING;

 device_links_write_unlock();
}

/**
 * device_links_driver_bound - Update device links after probing its driver.
 * @dev: Device to update the links for.
 *
 * The probe has been successful, so update links from this device to any
 * consumers by changing their status to "available".
 *
 * Also change the status of @dev's links to suppliers to "active".
 *
 * Links without the DL_FLAG_MANAGED flag set are ignored.
 */

void device_links_driver_bound(struct device *dev)
{
 struct device_link *link, *ln;
 LIST_HEAD(sync_list);

 /*
 * If a device binds successfully, it's expected to have created all
 * the device links it needs to or make new device links as it needs
 * them. So, fw_devlink no longer needs to create device links to any
 * of the device's suppliers.
 *
 * Also, if a child firmware node of this bound device is not added as a
 * device by now, assume it is never going to be added. Make this bound
 * device the fallback supplier to the dangling consumers of the child
 * firmware node because this bound device is probably implementing the
 * child firmware node functionality and we don't want the dangling
 * consumers to defer probe indefinitely waiting for a device for the
 * child firmware node.
 */

 if (dev->fwnode && dev->fwnode->dev == dev) {
  struct fwnode_handle *child;

  fwnode_links_purge_suppliers(dev->fwnode);

  guard(mutex)(&fwnode_link_lock);

  fwnode_for_each_available_child_node(dev->fwnode, child)
   __fw_devlink_pickup_dangling_consumers(child,
              dev->fwnode);
  __fw_devlink_link_to_consumers(dev);
 }
 device_remove_file(dev, &dev_attr_waiting_for_supplier);

 device_links_write_lock();

 list_for_each_entry(link, &dev->links.consumers, s_node) {
  if (!device_link_test(link, DL_FLAG_MANAGED))
   continue;

  /*
 * Links created during consumer probe may be in the "consumer
 * probe" state to start with if the supplier is still probing
 * when they are created and they may become "active" if the
 * consumer probe returns first.  Skip them here.
 */

  if (link->status == DL_STATE_CONSUMER_PROBE ||
      link->status == DL_STATE_ACTIVE)
   continue;

  WARN_ON(link->status != DL_STATE_DORMANT);
  WRITE_ONCE(link->status, DL_STATE_AVAILABLE);

  if (device_link_test(link, DL_FLAG_AUTOPROBE_CONSUMER))
   driver_deferred_probe_add(link->consumer);
 }

 if (defer_sync_state_count)
  __device_links_supplier_defer_sync(dev);
 else
  __device_links_queue_sync_state(dev, &sync_list);

 list_for_each_entry_safe(link, ln, &dev->links.suppliers, c_node) {
  struct device *supplier;

  if (!device_link_test(link, DL_FLAG_MANAGED))
   continue;

  supplier = link->supplier;
  if (device_link_test(link, DL_FLAG_SYNC_STATE_ONLY)) {
   /*
 * When DL_FLAG_SYNC_STATE_ONLY is set, it means no
 * other DL_MANAGED_LINK_FLAGS have been set. So, it's
 * save to drop the managed link completely.
 */

   device_link_drop_managed(link);
  } else if (dev_is_best_effort(dev) &&
      device_link_test(link, DL_FLAG_INFERRED) &&
      link->status != DL_STATE_CONSUMER_PROBE &&
      !link->supplier->can_match) {
   /*
 * When dev_is_best_effort() is true, we ignore device
 * links to suppliers that don't have a driver.  If the
 * consumer device still managed to probe, there's no
 * point in maintaining a device link in a weird state
 * (consumer probed before supplier). So delete it.
 */

   device_link_drop_managed(link);
  } else {
   WARN_ON(link->status != DL_STATE_CONSUMER_PROBE);
   WRITE_ONCE(link->status, DL_STATE_ACTIVE);
  }

  /*
 * This needs to be done even for the deleted
 * DL_FLAG_SYNC_STATE_ONLY device link in case it was the last
 * device link that was preventing the supplier from getting a
 * sync_state() call.
 */

  if (defer_sync_state_count)
   __device_links_supplier_defer_sync(supplier);
  else
   __device_links_queue_sync_state(supplier, &sync_list);
 }

 dev->links.status = DL_DEV_DRIVER_BOUND;

 device_links_write_unlock();

 device_links_flush_sync_list(&sync_list, dev);
}

/**
 * __device_links_no_driver - Update links of a device without a driver.
 * @dev: Device without a drvier.
 *
 * Delete all non-persistent links from this device to any suppliers.
 *
 * Persistent links stay around, but their status is changed to "available",
 * unless they already are in the "supplier unbind in progress" state in which
 * case they need not be updated.
 *
 * 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 (!device_link_test(link, DL_FLAG_MANAGED))
   continue;

  if (device_link_test(link, DL_FLAG_AUTOREMOVE_CONSUMER)) {
   device_link_drop_managed(link);
   continue;
  }

  if (link->status != DL_STATE_CONSUMER_PROBE &&
      link->status != DL_STATE_ACTIVE)
   continue;

  if (link->supplier->links.status == DL_DEV_DRIVER_BOUND) {
   WRITE_ONCE(link->status, DL_STATE_AVAILABLE);
  } else {
   WARN_ON(!device_link_test(link, DL_FLAG_SYNC_STATE_ONLY));
   WRITE_ONCE(link->status, DL_STATE_DORMANT);
  }
 }

 dev->links.status = DL_DEV_NO_DRIVER;
}

/**
 * device_links_no_driver - Update links after failing driver probe.
 * @dev: Device whose driver has just failed to probe.
 *
 * Clean up leftover links to consumers for @dev and invoke
 * %__device_links_no_driver() to update links to suppliers for it as
 * appropriate.
 *
 * Links without the DL_FLAG_MANAGED flag set are ignored.
 */

void device_links_no_driver(struct device *dev)
{
 struct device_link *link;

 device_links_write_lock();

 list_for_each_entry(link, &dev->links.consumers, s_node) {
  if (!device_link_test(link, DL_FLAG_MANAGED))
   continue;

  /*
 * The probe has failed, so if the status of the link is
 * "consumer probe" or "active", it must have been added by
 * a probing consumer while this device was still probing.
 * Change its state to "dormant", as it represents a valid
 * relationship, but it is not functionally meaningful.
 */

  if (link->status == DL_STATE_CONSUMER_PROBE ||
      link->status == DL_STATE_ACTIVE)
   WRITE_ONCE(link->status, DL_STATE_DORMANT);
 }

 __device_links_no_driver(dev);

 device_links_write_unlock();
}

/**
 * device_links_driver_cleanup - Update links after driver removal.
 * @dev: Device whose driver has just gone away.
 *
 * Update links to consumers for @dev by changing their status to "dormant" and
 * invoke %__device_links_no_driver() to update links to suppliers for it as
 * appropriate.
 *
 * Links without the DL_FLAG_MANAGED flag set are ignored.
 */

void device_links_driver_cleanup(struct device *dev)
{
 struct device_link *link, *ln;

 device_links_write_lock();

 list_for_each_entry_safe(link, ln, &dev->links.consumers, s_node) {
  if (!device_link_test(link, DL_FLAG_MANAGED))
   continue;

  WARN_ON(device_link_test(link, DL_FLAG_AUTOREMOVE_CONSUMER));
  WARN_ON(link->status != DL_STATE_SUPPLIER_UNBIND);

  /*
 * autoremove the links between this @dev and its consumer
 * devices that are not active, i.e. where the link state
 * has moved to DL_STATE_SUPPLIER_UNBIND.
 */

  if (link->status == DL_STATE_SUPPLIER_UNBIND &&
      device_link_test(link, DL_FLAG_AUTOREMOVE_SUPPLIER))
   device_link_drop_managed(link);

  WRITE_ONCE(link->status, DL_STATE_DORMANT);
 }

 list_del_init(&dev->links.defer_sync);
 __device_links_no_driver(dev);

 device_links_write_unlock();
}

/**
 * device_links_busy - Check if there are any busy links to consumers.
 * @dev: Device to check.
 *
 * Check each consumer of the device and return 'true' if its link's status
 * is one of "consumer probe" or "active" (meaning that the given consumer is
 * probing right now or its driver is present).  Otherwise, change the link
 * state to "supplier unbind" to prevent the consumer from being probed
 * successfully going forward.
 *
 * Return 'false' if there are no probing or active consumers.
 *
 * Links without the DL_FLAG_MANAGED flag set are ignored.
 */

bool device_links_busy(struct device *dev)
{
 struct device_link *link;
 bool ret = false;

 device_links_write_lock();

 list_for_each_entry(link, &dev->links.consumers, s_node) {
  if (!device_link_test(link, DL_FLAG_MANAGED))
   continue;

  if (link->status == DL_STATE_CONSUMER_PROBE
      || link->status == DL_STATE_ACTIVE) {
   ret = true;
   break;
  }
  WRITE_ONCE(link->status, DL_STATE_SUPPLIER_UNBIND);
 }

 dev->links.status = DL_DEV_UNBINDING;

 device_links_write_unlock();
 return ret;
}

/**
 * device_links_unbind_consumers - Force unbind consumers of the given device.
 * @dev: Device to unbind the consumers of.
 *
 * Walk the list of links to consumers for @dev and if any of them is in the
 * "consumer probe" state, wait for all device probes in progress to complete
 * and start over.
 *
 * If that's not the case, change the status of the link to "supplier unbind"
 * and check if the link was in the "active" state.  If so, force the consumer
 * driver to unbind and start over (the consumer will not re-probe as we have
 * changed the state of the link already).
 *
 * Links without the DL_FLAG_MANAGED flag set are ignored.
 */

void device_links_unbind_consumers(struct device *dev)
{
 struct device_link *link;

 start:
 device_links_write_lock();

 list_for_each_entry(link, &dev->links.consumers, s_node) {
  enum device_link_state status;

  if (!device_link_test(link, DL_FLAG_MANAGED) ||
      device_link_test(link, DL_FLAG_SYNC_STATE_ONLY))
   continue;

  status = link->status;
  if (status == DL_STATE_CONSUMER_PROBE) {
   device_links_write_unlock();

   wait_for_device_probe();
   goto start;
  }
  WRITE_ONCE(link->status, DL_STATE_SUPPLIER_UNBIND);
  if (status == DL_STATE_ACTIVE) {
   struct device *consumer = link->consumer;

   get_device(consumer);

   device_links_write_unlock();

   device_release_driver_internal(consumer, NULL,
             consumer->parent);
   put_device(consumer);
   goto start;
  }
 }

 device_links_write_unlock();
}

/**
 * device_links_purge - Delete existing links to other devices.
 * @dev: Target device.
 */

static void device_links_purge(struct device *dev)
{
 struct device_link *link, *ln;

 if (dev->class == &devlink_class)
  return;

 /*
 * Delete all of the remaining links from this device to any other
 * devices (either consumers or suppliers).
 */

 device_links_write_lock();

 list_for_each_entry_safe_reverse(link, ln, &dev->links.suppliers, c_node) {
  WARN_ON(link->status == DL_STATE_ACTIVE);
  __device_link_del(&link->kref);
 }

 list_for_each_entry_safe_reverse(link, ln, &dev->links.consumers, s_node) {
  WARN_ON(link->status != DL_STATE_DORMANT &&
   link->status != DL_STATE_NONE);
  __device_link_del(&link->kref);
 }

 device_links_write_unlock();
}

#define FW_DEVLINK_FLAGS_PERMISSIVE (DL_FLAG_INFERRED | \
      DL_FLAG_SYNC_STATE_ONLY)
#define FW_DEVLINK_FLAGS_ON  (DL_FLAG_INFERRED | \
      DL_FLAG_AUTOPROBE_CONSUMER)
#define FW_DEVLINK_FLAGS_RPM  (FW_DEVLINK_FLAGS_ON | \
      DL_FLAG_PM_RUNTIME)

static u32 fw_devlink_flags = FW_DEVLINK_FLAGS_RPM;
static int __init fw_devlink_setup(char *arg)
{
 if (!arg)
  return -EINVAL;

 if (strcmp(arg, "off") == 0) {
  fw_devlink_flags = 0;
 } else if (strcmp(arg, "permissive") == 0) {
  fw_devlink_flags = FW_DEVLINK_FLAGS_PERMISSIVE;
 } else if (strcmp(arg, "on") == 0) {
  fw_devlink_flags = FW_DEVLINK_FLAGS_ON;
 } else if (strcmp(arg, "rpm") == 0) {
  fw_devlink_flags = FW_DEVLINK_FLAGS_RPM;
 }
 return 0;
}
early_param("fw_devlink", fw_devlink_setup);

static bool fw_devlink_strict;
static int __init fw_devlink_strict_setup(char *arg)
{
 return kstrtobool(arg, &fw_devlink_strict);
}
early_param("fw_devlink.strict", fw_devlink_strict_setup);

#define FW_DEVLINK_SYNC_STATE_STRICT 0
#define FW_DEVLINK_SYNC_STATE_TIMEOUT 1

#ifndef CONFIG_FW_DEVLINK_SYNC_STATE_TIMEOUT
static int fw_devlink_sync_state;
#else
static int fw_devlink_sync_state = FW_DEVLINK_SYNC_STATE_TIMEOUT;
#endif

static int __init fw_devlink_sync_state_setup(char *arg)
{
 if (!arg)
  return -EINVAL;

 if (strcmp(arg, "strict") == 0) {
  fw_devlink_sync_state = FW_DEVLINK_SYNC_STATE_STRICT;
  return 0;
 } else if (strcmp(arg, "timeout") == 0) {
  fw_devlink_sync_state = FW_DEVLINK_SYNC_STATE_TIMEOUT;
  return 0;
 }
 return -EINVAL;
}
early_param("fw_devlink.sync_state", fw_devlink_sync_state_setup);

static inline u32 fw_devlink_get_flags(u8 fwlink_flags)
{
 if (fwlink_flags & FWLINK_FLAG_CYCLE)
  return FW_DEVLINK_FLAGS_PERMISSIVE | DL_FLAG_CYCLE;

 return fw_devlink_flags;
}

static bool fw_devlink_is_permissive(void)
{
 return fw_devlink_flags == FW_DEVLINK_FLAGS_PERMISSIVE;
}

bool fw_devlink_is_strict(void)
{
 return fw_devlink_strict && !fw_devlink_is_permissive();
}

static void fw_devlink_parse_fwnode(struct fwnode_handle *fwnode)
{
 if (fwnode->flags & FWNODE_FLAG_LINKS_ADDED)
  return;

 fwnode_call_int_op(fwnode, add_links);
 fwnode->flags |= FWNODE_FLAG_LINKS_ADDED;
}

static void fw_devlink_parse_fwtree(struct fwnode_handle *fwnode)
{
 struct fwnode_handle *child = NULL;

 fw_devlink_parse_fwnode(fwnode);

 while ((child = fwnode_get_next_available_child_node(fwnode, child)))
  fw_devlink_parse_fwtree(child);
}

static void fw_devlink_relax_link(struct device_link *link)
{
 if (!device_link_test(link, DL_FLAG_INFERRED))
  return;

 if (device_link_flag_is_sync_state_only(link->flags))
  return;

 pm_runtime_drop_link(link);
 link->flags = DL_FLAG_MANAGED | FW_DEVLINK_FLAGS_PERMISSIVE;
 dev_dbg(link->consumer, "Relaxing link with %s\n",
  dev_name(link->supplier));
}

static int fw_devlink_no_driver(struct device *dev, void *data)
{
 struct device_link *link = to_devlink(dev);

 if (!link->supplier->can_match)
  fw_devlink_relax_link(link);

 return 0;
}

void fw_devlink_drivers_done(void)
{
 fw_devlink_drv_reg_done = true;
 device_links_write_lock();
 class_for_each_device(&devlink_class, NULL, NULL,
         fw_devlink_no_driver);
 device_links_write_unlock();
}

static int fw_devlink_dev_sync_state(struct device *dev, void *data)
{
 struct device_link *link = to_devlink(dev);
 struct device *sup = link->supplier;

 if (!device_link_test(link, DL_FLAG_MANAGED) ||
     link->status == DL_STATE_ACTIVE || sup->state_synced ||
     !dev_has_sync_state(sup))
  return 0;

 if (fw_devlink_sync_state == FW_DEVLINK_SYNC_STATE_STRICT) {
  dev_warn(sup, "sync_state() pending due to %s\n",
    dev_name(link->consumer));
  return 0;
 }

 if (!list_empty(&sup->links.defer_sync))
  return 0;

 dev_warn(sup, "Timed out. Forcing sync_state()\n");
 sup->state_synced = true;
 get_device(sup);
 list_add_tail(&sup->links.defer_sync, data);

 return 0;
}

void fw_devlink_probing_done(void)
{
 LIST_HEAD(sync_list);

 device_links_write_lock();
 class_for_each_device(&devlink_class, NULL, &sync_list,
         fw_devlink_dev_sync_state);
 device_links_write_unlock();
 device_links_flush_sync_list(&sync_list, NULL);
}

/**
 * wait_for_init_devices_probe - Try to probe any device needed for init
 *
 * Some devices might need to be probed and bound successfully before the kernel
 * boot sequence can finish and move on to init/userspace. For example, a
 * network interface might need to be bound to be able to mount a NFS rootfs.
 *
 * With fw_devlink=on by default, some of these devices might be blocked from
 * probing because they are waiting on a optional supplier that doesn't have a
 * driver. While fw_devlink will eventually identify such devices and unblock
 * the probing automatically, it might be too late by the time it unblocks the
 * probing of devices. For example, the IP4 autoconfig might timeout before
 * fw_devlink unblocks probing of the network interface.
 *
 * This function is available to temporarily try and probe all devices that have
 * a driver even if some of their suppliers haven't been added or don't have
 * drivers.
 *
 * The drivers can then decide which of the suppliers are optional vs mandatory
 * and probe the device if possible. By the time this function returns, all such
 * "best effort" probes are guaranteed to be completed. If a device successfully
 * probes in this mode, we delete all fw_devlink discovered dependencies of that
 * device where the supplier hasn't yet probed successfully because they have to
 * be optional dependencies.
 *
 * Any devices that didn't successfully probe go back to being treated as if
 * this function was never called.
 *
 * This also means that some devices that aren't needed for init and could have
 * waited for their optional supplier to probe (when the supplier's module is
 * loaded later on) would end up probing prematurely with limited functionality.
 * So call this function only when boot would fail without it.
 */

void __init wait_for_init_devices_probe(void)
{
 if (!fw_devlink_flags || fw_devlink_is_permissive())
  return;

 /*
 * Wait for all ongoing probes to finish so that the "best effort" is
 * only applied to devices that can't probe otherwise.
 */

 wait_for_device_probe();

 pr_info("Trying to probe devices needed for running init ...\n");
 fw_devlink_best_effort = true;
 driver_deferred_probe_trigger();

 /*
 * Wait for all "best effort" probes to finish before going back to
 * normal enforcement.
 */

 wait_for_device_probe();
 fw_devlink_best_effort = false;
}

static void fw_devlink_unblock_consumers(struct device *dev)
{
 struct device_link *link;

 if (!fw_devlink_flags || fw_devlink_is_permissive())
  return;

 device_links_write_lock();
 list_for_each_entry(link, &dev->links.consumers, s_node)
  fw_devlink_relax_link(link);
 device_links_write_unlock();
}

static bool fwnode_init_without_drv(struct fwnode_handle *fwnode)
{
 struct device *dev;
 bool ret;

 if (!(fwnode->flags & FWNODE_FLAG_INITIALIZED))
  return false;

 dev = get_dev_from_fwnode(fwnode);
 ret = !dev || dev->links.status == DL_DEV_NO_DRIVER;
 put_device(dev);

 return ret;
}

static bool fwnode_ancestor_init_without_drv(struct fwnode_handle *fwnode)
{
 struct fwnode_handle *parent;

 fwnode_for_each_parent_node(fwnode, parent) {
  if (fwnode_init_without_drv(parent)) {
   fwnode_handle_put(parent);
   return true;
  }
 }

 return false;
}

/**
 * fwnode_is_ancestor_of - Test if @ancestor is ancestor of @child
 * @ancestor: Firmware which is tested for being an ancestor
 * @child: Firmware which is tested for being the child
 *
 * A node is considered an ancestor of itself too.
 *
 * Return: true if @ancestor is an ancestor of @child. Otherwise, returns false.
 */

static bool fwnode_is_ancestor_of(const struct fwnode_handle *ancestor,
      const struct fwnode_handle *child)
{
 struct fwnode_handle *parent;

 if (IS_ERR_OR_NULL(ancestor))
  return false;

 if (child == ancestor)
  return true;

 fwnode_for_each_parent_node(child, parent) {
  if (parent == ancestor) {
   fwnode_handle_put(parent);
   return true;
  }
 }
 return false;
}

/**
 * fwnode_get_next_parent_dev - Find device of closest ancestor fwnode
 * @fwnode: firmware node
 *
 * Given a firmware node (@fwnode), this function finds its closest ancestor
 * firmware node that has a corresponding struct device and returns that struct
 * device.
 *
 * The caller is responsible for calling put_device() on the returned device
 * pointer.
 *
 * Return: a pointer to the device of the @fwnode's closest ancestor.
 */

static struct device *fwnode_get_next_parent_dev(const struct fwnode_handle *fwnode)
{
 struct fwnode_handle *parent;
 struct device *dev;

 fwnode_for_each_parent_node(fwnode, parent) {
  dev = get_dev_from_fwnode(parent);
  if (dev) {
   fwnode_handle_put(parent);
   return dev;
  }
 }
 return NULL;
}

/**
 * __fw_devlink_relax_cycles - Relax and mark dependency cycles.
 * @con_handle: Potential consumer device fwnode.
 * @sup_handle: Potential supplier's fwnode.
 *
 * Needs to be called with fwnode_lock and device link lock held.
 *
 * Check if @sup_handle or any of its ancestors or suppliers direct/indirectly
 * depend on @con. This function can detect multiple cyles between @sup_handle
 * and @con. When such dependency cycles are found, convert all device links
 * created solely by fw_devlink into SYNC_STATE_ONLY device links. Also, mark
 * all fwnode links in the cycle with FWLINK_FLAG_CYCLE so that when they are
 * converted into a device link in the future, they are created as
 * SYNC_STATE_ONLY device links. This is the equivalent of doing
 * fw_devlink=permissive just between the devices in the cycle. We need to do
 * this because, at this point, fw_devlink can't tell which of these
 * dependencies is not a real dependency.
 *
 * Return true if one or more cycles were found. Otherwise, return false.
 */

static bool __fw_devlink_relax_cycles(struct fwnode_handle *con_handle,
     struct fwnode_handle *sup_handle)
{
 struct device *sup_dev = NULL, *par_dev = NULL, *con_dev = NULL;
 struct fwnode_link *link;
 struct device_link *dev_link;
 bool ret = false;

 if (!sup_handle)
  return false;

 /*
 * We aren't trying to find all cycles. Just a cycle between con and
 * sup_handle.
 */

 if (sup_handle->flags & FWNODE_FLAG_VISITED)
  return false;

 sup_handle->flags |= FWNODE_FLAG_VISITED;

 /* Termination condition. */
 if (sup_handle == con_handle) {
  pr_debug("----- cycle: start -----\n");
  ret = true;
  goto out;
 }

 sup_dev = get_dev_from_fwnode(sup_handle);
 con_dev = get_dev_from_fwnode(con_handle);
 /*
 * If sup_dev is bound to a driver and @con hasn't started binding to a
 * driver, sup_dev can't be a consumer of @con. So, no need to check
 * further.
 */

 if (sup_dev && sup_dev->links.status ==  DL_DEV_DRIVER_BOUND &&
     con_dev && con_dev->links.status == DL_DEV_NO_DRIVER) {
  ret = false;
  goto out;
 }

 list_for_each_entry(link, &sup_handle->suppliers, c_hook) {
  if (link->flags & FWLINK_FLAG_IGNORE)
   continue;

  if (__fw_devlink_relax_cycles(con_handle, link->supplier)) {
   __fwnode_link_cycle(link);
   ret = true;
  }
 }

 /*
 * Give priority to device parent over fwnode parent to account for any
 * quirks in how fwnodes are converted to devices.
 */

 if (sup_dev)
  par_dev = get_device(sup_dev->parent);
 else
  par_dev = fwnode_get_next_parent_dev(sup_handle);

 if (par_dev && __fw_devlink_relax_cycles(con_handle, par_dev->fwnode)) {
  pr_debug("%pfwf: cycle: child of %pfwf\n", sup_handle,
    par_dev->fwnode);
  ret = true;
 }

 if (!sup_dev)
  goto out;

 list_for_each_entry(dev_link, &sup_dev->links.suppliers, c_node) {
  /*
 * Ignore a SYNC_STATE_ONLY flag only if it wasn't marked as
 * such due to a cycle.
 */

  if (device_link_flag_is_sync_state_only(dev_link->flags) &&
      !device_link_test(dev_link, DL_FLAG_CYCLE))
   continue;

  if (__fw_devlink_relax_cycles(con_handle,
           dev_link->supplier->fwnode)) {
   pr_debug("%pfwf: cycle: depends on %pfwf\n", sup_handle,
     dev_link->supplier->fwnode);
   fw_devlink_relax_link(dev_link);
   dev_link->flags |= DL_FLAG_CYCLE;
   ret = true;
  }
 }

out:
 sup_handle->flags &= ~FWNODE_FLAG_VISITED;
 put_device(sup_dev);
 put_device(con_dev);
 put_device(par_dev);
 return ret;
}

/**
 * fw_devlink_create_devlink - Create a device link from a consumer to fwnode
 * @con: consumer device for the device link
 * @sup_handle: fwnode handle of supplier
 * @link: fwnode link that's being converted to a device link
 *
 * This function will try to create a device link between the consumer device
 * @con and the supplier device represented by @sup_handle.
 *
 * The supplier has to be provided as a fwnode because incorrect cycles in
 * fwnode links can sometimes cause the supplier device to never be created.
 * This function detects such cases and returns an error if it cannot create a
 * device link from the consumer to a missing supplier.
 *
 * Returns,
 * 0 on successfully creating a device link
 * -EINVAL if the device link cannot be created as expected
 * -EAGAIN if the device link cannot be created right now, but it may be
 *  possible to do that in the future
 */

static int fw_devlink_create_devlink(struct device *con,
         struct fwnode_handle *sup_handle,
         struct fwnode_link *link)
{
 struct device *sup_dev;
 int ret = 0;
 u32 flags;

 if (link->flags & FWLINK_FLAG_IGNORE)
  return 0;

 /*
 * In some cases, a device P might also be a supplier to its child node
 * C. However, this would defer the probe of C until the probe of P
 * completes successfully. This is perfectly fine in the device driver
 * model. device_add() doesn't guarantee probe completion of the device
 * by the time it returns.
 *
 * However, there are a few drivers that assume C will finish probing
 * as soon as it's added and before P finishes probing. So, we provide
 * a flag to let fw_devlink know not to delay the probe of C until the
 * probe of P completes successfully.
 *
 * When such a flag is set, we can't create device links where P is the
 * supplier of C as that would delay the probe of C.
 */

 if (sup_handle->flags & FWNODE_FLAG_NEEDS_CHILD_BOUND_ON_ADD &&
     fwnode_is_ancestor_of(sup_handle, con->fwnode))
  return -EINVAL;

 /*
 * Don't try to optimize by not calling the cycle detection logic under
 * certain conditions. There's always some corner case that won't get
 * detected.
 */

 device_links_write_lock();
 if (__fw_devlink_relax_cycles(link->consumer, sup_handle)) {
  __fwnode_link_cycle(link);
  pr_debug("----- cycle: end -----\n");
  pr_info("%pfwf: Fixed dependency cycle(s) with %pfwf\n",
   link->consumer, sup_handle);
 }
 device_links_write_unlock();

 if (con->fwnode == link->consumer)
  flags = fw_devlink_get_flags(link->flags);
 else
  flags = FW_DEVLINK_FLAGS_PERMISSIVE;

 if (sup_handle->flags & FWNODE_FLAG_NOT_DEVICE)
  sup_dev = fwnode_get_next_parent_dev(sup_handle);
 else
  sup_dev = get_dev_from_fwnode(sup_handle);

 if (sup_dev) {
  /*
 * If it's one of those drivers that don't actually bind to
 * their device using driver core, then don't wait on this
 * supplier device indefinitely.
 */

  if (sup_dev->links.status == DL_DEV_NO_DRIVER &&
      sup_handle->flags & FWNODE_FLAG_INITIALIZED) {
   dev_dbg(con,
    "Not linking %pfwf - dev might never probe\n",
    sup_handle);
   ret = -EINVAL;
   goto out;
  }

  if (con != sup_dev && !device_link_add(con, sup_dev, flags)) {
   dev_err(con, "Failed to create device link (0x%x) with supplier %s for %pfwf\n",
    flags, dev_name(sup_dev), link->consumer);
   ret = -EINVAL;
  }

  goto out;
 }

 /*
 * Supplier or supplier's ancestor already initialized without a struct
 * device or being probed by a driver.
 */

 if (fwnode_init_without_drv(sup_handle) ||
     fwnode_ancestor_init_without_drv(sup_handle)) {
  dev_dbg(con, "Not linking %pfwf - might never become dev\n",
   sup_handle);
  return -EINVAL;
 }

 ret = -EAGAIN;
out:
 put_device(sup_dev);
 return ret;
}

/**
 * __fw_devlink_link_to_consumers - Create device links to consumers of a device
 * @dev: Device that needs to be linked to its consumers
 *
 * This function looks at all the consumer fwnodes of @dev and creates device
 * links between the consumer device and @dev (supplier).
 *
 * If the consumer device has not been added yet, then this function creates a
 * SYNC_STATE_ONLY link between @dev (supplier) and the closest ancestor device
 * of the consumer fwnode. This is necessary to make sure @dev doesn't get a
 * sync_state() callback before the real consumer device gets to be added and
 * then probed.
 *
 * Once device links are created from the real consumer to @dev (supplier), the
 * fwnode links are deleted.
 */

static void __fw_devlink_link_to_consumers(struct device *dev)
{
 struct fwnode_handle *fwnode = dev->fwnode;
 struct fwnode_link *link, *tmp;

 list_for_each_entry_safe(link, tmp, &fwnode->consumers, s_hook) {
  struct device *con_dev;
  bool own_link = true;
  int ret;

  con_dev = get_dev_from_fwnode(link->consumer);
  /*
 * If consumer device is not available yet, make a "proxy"
 * SYNC_STATE_ONLY link from the consumer's parent device to
 * the supplier device. This is necessary to make sure the
 * supplier doesn't get a sync_state() callback before the real
 * consumer can create a device link to the supplier.
 *
 * This proxy link step is needed to handle the case where the
 * consumer's parent device is added before the supplier.
 */

  if (!con_dev) {
   con_dev = fwnode_get_next_parent_dev(link->consumer);
   /*
 * However, if the consumer's parent device is also the
 * parent of the supplier, don't create a
 * consumer-supplier link from the parent to its child
 * device. Such a dependency is impossible.
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=95 H=93 G=93

¤ Dauer der Verarbeitung: 0.23 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.