Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 57f27753 authored by Saravana Kannan's avatar Saravana Kannan Committed by Srinivasarao P
Browse files

UPSTREAM: driver core: Add device link support for SYNC_STATE_ONLY flag



Parent devices might need to create "proxy" device links from themselves
to supplier devices to make sure the supplier devices don't get a
sync_state() before the child consumer devices get a chance to add
device links to the supplier devices.

However, the parent device has no real dependency on the supplier device
and probing, suspend/resume or runtime PM don't need to be affected by
the supplier device.  To capture these cases, create a SYNC_STATE_ONLY
device link flag that only affects sync_state() behavior and doesn't
affect probing, suspend/resume or runtime PM.

Signed-off-by: default avatarSaravana Kannan <saravanak@google.com>
Link: https://lore.kernel.org/r/20191028220027.251605-2-saravanak@google.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
(cherry picked from commit 05ef983e0d65a31b370a4e1b93c1efd490ae778f)
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@google.com>
Change-Id: I4034d50f34f199feebed40f3a055d7aa4bd31e2c
Git-repo: https://android.googlesource.com/kernel/common


Git-commit: 6bda9344
Signed-off-by: default avatarSrinivasarao P <spathi@codeaurora.org>
parent 417d28a4
Loading
Loading
Loading
Loading
+41 −9
Original line number Diff line number Diff line
@@ -118,6 +118,9 @@ static int device_is_dependent(struct device *dev, void *target)
		return ret;

	list_for_each_entry(link, &dev->links.consumers, s_node) {
		if (link->flags == (DL_FLAG_SYNC_STATE_ONLY | DL_FLAG_MANAGED))
			continue;

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

@@ -187,8 +190,11 @@ static int device_reorder_to_tail(struct device *dev, void *not_used)
		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)
	list_for_each_entry(link, &dev->links.consumers, s_node) {
		if (link->flags == (DL_FLAG_SYNC_STATE_ONLY | DL_FLAG_MANAGED))
			continue;
		device_reorder_to_tail(link->consumer, NULL);
	}

	return 0;
}
@@ -215,7 +221,8 @@ void device_pm_move_to_tail(struct device *dev)

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

#define DL_ADD_VALID_FLAGS (DL_MANAGED_LINK_FLAGS | DL_FLAG_STATELESS | \
			    DL_FLAG_PM_RUNTIME | DL_FLAG_RPM_ACTIVE)
@@ -283,6 +290,8 @@ struct device_link *device_link_add(struct device *consumer,

	if (!consumer || !supplier || flags & ~DL_ADD_VALID_FLAGS ||
	    (flags & DL_FLAG_STATELESS && flags & DL_MANAGED_LINK_FLAGS) ||
	    (flags & DL_FLAG_SYNC_STATE_ONLY &&
	     flags != DL_FLAG_SYNC_STATE_ONLY) ||
	    (flags & DL_FLAG_AUTOPROBE_CONSUMER &&
	     flags & (DL_FLAG_AUTOREMOVE_CONSUMER |
		      DL_FLAG_AUTOREMOVE_SUPPLIER)))
@@ -303,11 +312,14 @@ struct device_link *device_link_add(struct device *consumer,

	/*
	 * If the supplier has not been fully registered yet or there is a
	 * reverse dependency between the consumer and the supplier already in
	 * the graph, return NULL.
	 * 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)
	    || device_is_dependent(consumer, supplier)) {
	    || (!(flags & DL_FLAG_SYNC_STATE_ONLY) &&
		  device_is_dependent(consumer, supplier))) {
		link = NULL;
		goto out;
	}
@@ -334,10 +346,15 @@ struct device_link *device_link_add(struct device *consumer,
		}

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

		/*
		 * If the life time of the link following from the new flags is
@@ -358,6 +375,12 @@ struct device_link *device_link_add(struct device *consumer,
			link->flags |= DL_FLAG_MANAGED;
			device_link_init_status(link, consumer, supplier);
		}
		if (link->flags & DL_FLAG_SYNC_STATE_ONLY &&
		    !(flags & DL_FLAG_SYNC_STATE_ONLY)) {
			link->flags &= ~DL_FLAG_SYNC_STATE_ONLY;
			goto reorder;
		}

		goto out;
	}

@@ -397,6 +420,13 @@ struct device_link *device_link_add(struct device *consumer,
	    flags & DL_FLAG_PM_RUNTIME)
		pm_runtime_resume(supplier);

	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.
@@ -639,7 +669,8 @@ int device_links_check_suppliers(struct device *dev)
	device_links_write_lock();

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

		if (link->status != DL_STATE_AVAILABLE) {
@@ -1036,7 +1067,8 @@ 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_MANAGED))
		if (!(link->flags & DL_FLAG_MANAGED) ||
		    link->flags & DL_FLAG_SYNC_STATE_ONLY)
			continue;

		status = link->status;
+2 −0
Original line number Diff line number Diff line
@@ -849,6 +849,7 @@ enum device_link_state {
 * AUTOREMOVE_SUPPLIER: Remove the link automatically on supplier driver unbind.
 * AUTOPROBE_CONSUMER: Probe consumer driver automatically after supplier binds.
 * MANAGED: The core tracks presence of supplier/consumer drivers (internal).
 * SYNC_STATE_ONLY: Link only affects sync_state() behavior.
 */
#define DL_FLAG_STATELESS		BIT(0)
#define DL_FLAG_AUTOREMOVE_CONSUMER	BIT(1)
@@ -857,6 +858,7 @@ enum device_link_state {
#define DL_FLAG_AUTOREMOVE_SUPPLIER	BIT(4)
#define DL_FLAG_AUTOPROBE_CONSUMER	BIT(5)
#define DL_FLAG_MANAGED			BIT(6)
#define DL_FLAG_SYNC_STATE_ONLY		BIT(7)

/**
 * struct device_link - Device link representation.