Commit 266d17a8 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'driver-core-5.18-rc1' of...

Merge tag 'driver-core-5.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core

Pull driver core updates from Greg KH:
 "Here is the set of driver core changes for 5.18-rc1.

  Not much here, primarily it was a bunch of cleanups and small updates:

   - kobj_type cleanups for default_groups

   - documentation updates

   - firmware loader minor changes

   - component common helper added and take advantage of it in many
     drivers (the largest part of this pull request).

  All of these have been in linux-next for a while with no reported
  problems"

* tag 'driver-core-5.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: (54 commits)
  Documentation: update stable review cycle documentation
  drivers/base/dd.c : Remove the initial value of the global variable
  Documentation: update stable tree link
  Documentation: add link to stable release candidate tree
  devres: fix typos in comments
  Documentation: add note block surrounding security patch note
  samples/kobject: Use sysfs_emit instead of sprintf
  base: soc: Make soc_device_match() simpler and easier to read
  driver core: dd: fix return value of __setup handler
  driver core: Refactor sysfs and drv/bus remove hooks
  driver core: Refactor multiple copies of device cleanup
  scripts: get_abi.pl: Fix typo in help message
  kernfs: fix typos in comments
  kernfs: remove unneeded #if 0 guard
  ALSA: hda/realtek: Make use of the helper component_compare_dev_name
  video: omapfb: dss: Make use of the helper component_compare_dev
  power: supply: ab8500: Make use of the helper component_compare_dev
  ASoC: codecs: wcd938x: Make use of the helper component_compare/release_of
  iommu/mediatek: Make use of the helper component_compare/release_of
  drm: of: Make use of the helper component_release_of
  ...
parents 02e2af20 88d99e87
Loading
Loading
Loading
Loading
+26 −6
Original line number Diff line number Diff line
@@ -35,7 +35,9 @@ Rules on what kind of patches are accepted, and which ones are not, into the
Procedure for submitting patches to the -stable tree
----------------------------------------------------

 - Security patches should not be handled (solely) by the -stable review
.. note::

   Security patches should not be handled (solely) by the -stable review
   process but should follow the procedures in
   :ref:`Documentation/admin-guide/security-bugs.rst <securitybugs>`.

@@ -81,8 +83,8 @@ it to be applied to.
:ref:`option_2` and :ref:`option_3` are more useful if the patch isn't deemed
worthy at the time it is applied to a public git tree (for instance, because
it deserves more regression testing first).  :ref:`option_3` is especially
useful if the patch needs some special handling to apply to an older kernel
(e.g., if API's have changed in the meantime).
useful if the original upstream patch needs to be backported (for example
the backport needs some special handling due to e.g. API changes).

Note that for :ref:`option_3`, if the patch deviates from the original
upstream patch (for example because it had to be backported) this must be very
@@ -151,8 +153,17 @@ Review cycle
 - If the patch is rejected by a member of the committee, or linux-kernel
   members object to the patch, bringing up issues that the maintainers and
   members did not realize, the patch will be dropped from the queue.
 - At the end of the review cycle, the ACKed patches will be added to the
   latest -stable release, and a new -stable release will happen.
 - The ACKed patches will be posted again as part of release candidate (-rc)
   to be tested by developers and testers.
 - Usually only one -rc release is made, however if there are any outstanding
   issues, some patches may be modified or dropped or additional patches may
   be queued. Additional -rc releases are then released and tested until no
   issues are found.
 - Responding to the -rc releases can be done on the mailing list by sending
   a "Tested-by:" email with any testing information desired. The "Tested-by:"
   tags will be collected and added to the release commit.
 - At the end of the review cycle, the new -stable release will be released
   containing all the queued and tested patches.
 - Security patches will be accepted into the -stable tree directly from the
   security kernel team, and not go through the normal review cycle.
   Contact the kernel security team for more details on this procedure.
@@ -168,7 +179,16 @@ Trees
 - The finalized and tagged releases of all stable kernels can be found
   in separate branches per version at:

	https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git
	https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git

 - The release candidate of all stable kernel versions can be found at:

        https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git/

   .. warning::
      The -stable-rc tree is a snapshot in time of the stable-queue tree and
      will change frequently, hence will be rebased often. It should only be
      used for testing purposes (e.g. to be consumed by CI systems).


Review committee
+2 −2
Original line number Diff line number Diff line
@@ -3221,13 +3221,13 @@ static int __init rdtgroup_setup_root(void)

	list_add(&rdtgroup_default.rdtgroup_list, &rdt_all_groups);

	ret = rdtgroup_add_files(rdt_root->kn, RF_CTRL_BASE);
	ret = rdtgroup_add_files(kernfs_root_to_node(rdt_root), RF_CTRL_BASE);
	if (ret) {
		kernfs_destroy_root(rdt_root);
		goto out;
	}

	rdtgroup_default.kn = rdt_root->kn;
	rdtgroup_default.kn = kernfs_root_to_node(rdt_root);
	kernfs_activate(rdtgroup_default.kn);

out:
+177 −123
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
/*
 * Componentized device handling.
 *
 * This is work in progress.  We gather up the component devices into a list,
 * and bind them when instructed.  At the moment, we're specific to the DRM
 * subsystem, and only handles one master device, but this doesn't have to be
 * the case.
 */
#include <linux/component.h>
#include <linux/device.h>
#include <linux/list.h>
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/slab.h>
#include <linux/debugfs.h>

@@ -57,7 +53,7 @@ struct component_match {
	struct component_match_array *compare;
};

struct master {
struct aggregate_device {
	struct list_head node;
	bool bound;

@@ -68,7 +64,7 @@ struct master {

struct component {
	struct list_head node;
	struct master *master;
	struct aggregate_device *adev;
	bool bound;

	const struct component_ops *ops;
@@ -78,7 +74,7 @@ struct component {

static DEFINE_MUTEX(component_mutex);
static LIST_HEAD(component_list);
static LIST_HEAD(masters);
static LIST_HEAD(aggregate_devices);

#ifdef CONFIG_DEBUG_FS

@@ -86,12 +82,12 @@ static struct dentry *component_debugfs_dir;

static int component_devices_show(struct seq_file *s, void *data)
{
	struct master *m = s->private;
	struct aggregate_device *m = s->private;
	struct component_match *match = m->match;
	size_t i;

	mutex_lock(&component_mutex);
	seq_printf(s, "%-40s %20s\n", "master name", "status");
	seq_printf(s, "%-40s %20s\n", "aggregate_device name", "status");
	seq_puts(s, "-------------------------------------------------------------\n");
	seq_printf(s, "%-40s %20s\n\n",
		   dev_name(m->parent), m->bound ? "bound" : "not bound");
@@ -121,46 +117,46 @@ static int __init component_debug_init(void)

core_initcall(component_debug_init);

static void component_master_debugfs_add(struct master *m)
static void component_debugfs_add(struct aggregate_device *m)
{
	debugfs_create_file(dev_name(m->parent), 0444, component_debugfs_dir, m,
			    &component_devices_fops);
}

static void component_master_debugfs_del(struct master *m)
static void component_debugfs_del(struct aggregate_device *m)
{
	debugfs_remove(debugfs_lookup(dev_name(m->parent), component_debugfs_dir));
}

#else

static void component_master_debugfs_add(struct master *m)
static void component_debugfs_add(struct aggregate_device *m)
{ }

static void component_master_debugfs_del(struct master *m)
static void component_debugfs_del(struct aggregate_device *m)
{ }

#endif

static struct master *__master_find(struct device *parent,
static struct aggregate_device *__aggregate_find(struct device *parent,
	const struct component_master_ops *ops)
{
	struct master *m;
	struct aggregate_device *m;

	list_for_each_entry(m, &masters, node)
	list_for_each_entry(m, &aggregate_devices, node)
		if (m->parent == parent && (!ops || m->ops == ops))
			return m;

	return NULL;
}

static struct component *find_component(struct master *master,
static struct component *find_component(struct aggregate_device *adev,
	struct component_match_array *mc)
{
	struct component *c;

	list_for_each_entry(c, &component_list, node) {
		if (c->master && c->master != master)
		if (c->adev && c->adev != adev)
			continue;

		if (mc->compare && mc->compare(c->dev, mc->data))
@@ -174,102 +170,103 @@ static struct component *find_component(struct master *master,
	return NULL;
}

static int find_components(struct master *master)
static int find_components(struct aggregate_device *adev)
{
	struct component_match *match = master->match;
	struct component_match *match = adev->match;
	size_t i;
	int ret = 0;

	/*
	 * Scan the array of match functions and attach
	 * any components which are found to this master.
	 * any components which are found to this adev.
	 */
	for (i = 0; i < match->num; i++) {
		struct component_match_array *mc = &match->compare[i];
		struct component *c;

		dev_dbg(master->parent, "Looking for component %zu\n", i);
		dev_dbg(adev->parent, "Looking for component %zu\n", i);

		if (match->compare[i].component)
			continue;

		c = find_component(master, mc);
		c = find_component(adev, mc);
		if (!c) {
			ret = -ENXIO;
			break;
		}

		dev_dbg(master->parent, "found component %s, duplicate %u\n", dev_name(c->dev), !!c->master);
		dev_dbg(adev->parent, "found component %s, duplicate %u\n",
			dev_name(c->dev), !!c->adev);

		/* Attach this component to the master */
		match->compare[i].duplicate = !!c->master;
		/* Attach this component to the adev */
		match->compare[i].duplicate = !!c->adev;
		match->compare[i].component = c;
		c->master = master;
		c->adev = adev;
	}
	return ret;
}

/* Detach component from associated master */
static void remove_component(struct master *master, struct component *c)
/* Detach component from associated aggregate_device */
static void remove_component(struct aggregate_device *adev, struct component *c)
{
	size_t i;

	/* Detach the component from this master. */
	for (i = 0; i < master->match->num; i++)
		if (master->match->compare[i].component == c)
			master->match->compare[i].component = NULL;
	/* Detach the component from this adev. */
	for (i = 0; i < adev->match->num; i++)
		if (adev->match->compare[i].component == c)
			adev->match->compare[i].component = NULL;
}

/*
 * Try to bring up a master.  If component is NULL, we're interested in
 * this master, otherwise it's a component which must be present to try
 * and bring up the master.
 * Try to bring up an aggregate device.  If component is NULL, we're interested
 * in this aggregate device, otherwise it's a component which must be present
 * to try and bring up the aggregate device.
 *
 * Returns 1 for successful bringup, 0 if not ready, or -ve errno.
 */
static int try_to_bring_up_master(struct master *master,
static int try_to_bring_up_aggregate_device(struct aggregate_device *adev,
	struct component *component)
{
	int ret;

	dev_dbg(master->parent, "trying to bring up master\n");
	dev_dbg(adev->parent, "trying to bring up adev\n");

	if (find_components(master)) {
		dev_dbg(master->parent, "master has incomplete components\n");
	if (find_components(adev)) {
		dev_dbg(adev->parent, "master has incomplete components\n");
		return 0;
	}

	if (component && component->master != master) {
		dev_dbg(master->parent, "master is not for this component (%s)\n",
	if (component && component->adev != adev) {
		dev_dbg(adev->parent, "master is not for this component (%s)\n",
			dev_name(component->dev));
		return 0;
	}

	if (!devres_open_group(master->parent, master, GFP_KERNEL))
	if (!devres_open_group(adev->parent, adev, GFP_KERNEL))
		return -ENOMEM;

	/* Found all components */
	ret = master->ops->bind(master->parent);
	ret = adev->ops->bind(adev->parent);
	if (ret < 0) {
		devres_release_group(master->parent, NULL);
		devres_release_group(adev->parent, NULL);
		if (ret != -EPROBE_DEFER)
			dev_info(master->parent, "master bind failed: %d\n", ret);
			dev_info(adev->parent, "adev bind failed: %d\n", ret);
		return ret;
	}

	devres_close_group(master->parent, NULL);
	master->bound = true;
	devres_close_group(adev->parent, NULL);
	adev->bound = true;
	return 1;
}

static int try_to_bring_up_masters(struct component *component)
{
	struct master *m;
	struct aggregate_device *adev;
	int ret = 0;

	list_for_each_entry(m, &masters, node) {
		if (!m->bound) {
			ret = try_to_bring_up_master(m, component);
	list_for_each_entry(adev, &aggregate_devices, node) {
		if (!adev->bound) {
			ret = try_to_bring_up_aggregate_device(adev, component);
			if (ret != 0)
				break;
		}
@@ -278,14 +275,71 @@ static int try_to_bring_up_masters(struct component *component)
	return ret;
}

static void take_down_master(struct master *master)
static void take_down_aggregate_device(struct aggregate_device *adev)
{
	if (adev->bound) {
		adev->ops->unbind(adev->parent);
		devres_release_group(adev->parent, adev);
		adev->bound = false;
	}
}

/**
 * component_compare_of - A common component compare function for of_node
 * @dev: component device
 * @data: @compare_data from component_match_add_release()
 *
 * A common compare function when compare_data is device of_node. e.g.
 * component_match_add_release(masterdev, &match, component_release_of,
 * component_compare_of, component_dev_of_node)
 */
int component_compare_of(struct device *dev, void *data)
{
	if (master->bound) {
		master->ops->unbind(master->parent);
		devres_release_group(master->parent, master);
		master->bound = false;
	return device_match_of_node(dev, data);
}
EXPORT_SYMBOL_GPL(component_compare_of);

/**
 * component_release_of - A common component release function for of_node
 * @dev: component device
 * @data: @compare_data from component_match_add_release()
 *
 * About the example, Please see component_compare_of().
 */
void component_release_of(struct device *dev, void *data)
{
	of_node_put(data);
}
EXPORT_SYMBOL_GPL(component_release_of);

/**
 * component_compare_dev - A common component compare function for dev
 * @dev: component device
 * @data: @compare_data from component_match_add_release()
 *
 * A common compare function when compare_data is struce device. e.g.
 * component_match_add(masterdev, &match, component_compare_dev, component_dev)
 */
int component_compare_dev(struct device *dev, void *data)
{
	return dev == data;
}
EXPORT_SYMBOL_GPL(component_compare_dev);

/**
 * component_compare_dev_name - A common component compare function for device name
 * @dev: component device
 * @data: @compare_data from component_match_add_release()
 *
 * A common compare function when compare_data is device name string. e.g.
 * component_match_add(masterdev, &match, component_compare_dev_name,
 * "component_dev_name")
 */
int component_compare_dev_name(struct device *dev, void *data)
{
	return device_match_name(dev, data);
}
EXPORT_SYMBOL_GPL(component_compare_dev_name);

static void devm_component_match_release(struct device *parent, void *res)
{
@@ -324,7 +378,7 @@ static int component_match_realloc(struct component_match *match, size_t num)
	return 0;
}

static void __component_match_add(struct device *master,
static void __component_match_add(struct device *parent,
	struct component_match **matchptr,
	void (*release)(struct device *, void *),
	int (*compare)(struct device *, void *),
@@ -344,7 +398,7 @@ static void __component_match_add(struct device *master,
			return;
		}

		devres_add(master, match);
		devres_add(parent, match);

		*matchptr = match;
	}
@@ -370,13 +424,13 @@ static void __component_match_add(struct device *master,

/**
 * component_match_add_release - add a component match entry with release callback
 * @master: device with the aggregate driver
 * @parent: parent device of the aggregate driver
 * @matchptr: pointer to the list of component matches
 * @release: release function for @compare_data
 * @compare: compare function to match against all components
 * @compare_data: opaque pointer passed to the @compare function
 *
 * Adds a new component match to the list stored in @matchptr, which the @master
 * Adds a new component match to the list stored in @matchptr, which the
 * aggregate driver needs to function. The list of component matches pointed to
 * by @matchptr must be initialized to NULL before adding the first match. This
 * only matches against components added with component_add().
@@ -388,24 +442,24 @@ static void __component_match_add(struct device *master,
 *
 * See also component_match_add() and component_match_add_typed().
 */
void component_match_add_release(struct device *master,
void component_match_add_release(struct device *parent,
	struct component_match **matchptr,
	void (*release)(struct device *, void *),
	int (*compare)(struct device *, void *), void *compare_data)
{
	__component_match_add(master, matchptr, release, compare, NULL,
	__component_match_add(parent, matchptr, release, compare, NULL,
			      compare_data);
}
EXPORT_SYMBOL(component_match_add_release);

/**
 * component_match_add_typed - add a component match entry for a typed component
 * @master: device with the aggregate driver
 * @parent: parent device of the aggregate driver
 * @matchptr: pointer to the list of component matches
 * @compare_typed: compare function to match against all typed components
 * @compare_data: opaque pointer passed to the @compare function
 *
 * Adds a new component match to the list stored in @matchptr, which the @master
 * Adds a new component match to the list stored in @matchptr, which the
 * aggregate driver needs to function. The list of component matches pointed to
 * by @matchptr must be initialized to NULL before adding the first match. This
 * only matches against components added with component_add_typed().
@@ -415,32 +469,32 @@ EXPORT_SYMBOL(component_match_add_release);
 *
 * See also component_match_add_release() and component_match_add_typed().
 */
void component_match_add_typed(struct device *master,
void component_match_add_typed(struct device *parent,
	struct component_match **matchptr,
	int (*compare_typed)(struct device *, int, void *), void *compare_data)
{
	__component_match_add(master, matchptr, NULL, NULL, compare_typed,
	__component_match_add(parent, matchptr, NULL, NULL, compare_typed,
			      compare_data);
}
EXPORT_SYMBOL(component_match_add_typed);

static void free_master(struct master *master)
static void free_aggregate_device(struct aggregate_device *adev)
{
	struct component_match *match = master->match;
	struct component_match *match = adev->match;
	int i;

	component_master_debugfs_del(master);
	list_del(&master->node);
	component_debugfs_del(adev);
	list_del(&adev->node);

	if (match) {
		for (i = 0; i < match->num; i++) {
			struct component *c = match->compare[i].component;
			if (c)
				c->master = NULL;
				c->adev = NULL;
		}
	}

	kfree(master);
	kfree(adev);
}

/**
@@ -459,7 +513,7 @@ int component_master_add_with_match(struct device *parent,
	const struct component_master_ops *ops,
	struct component_match *match)
{
	struct master *master;
	struct aggregate_device *adev;
	int ret;

	/* Reallocate the match array for its true size */
@@ -467,23 +521,23 @@ int component_master_add_with_match(struct device *parent,
	if (ret)
		return ret;

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

	master->parent = parent;
	master->ops = ops;
	master->match = match;
	adev->parent = parent;
	adev->ops = ops;
	adev->match = match;

	component_master_debugfs_add(master);
	/* Add to the list of available masters. */
	component_debugfs_add(adev);
	/* Add to the list of available aggregate devices. */
	mutex_lock(&component_mutex);
	list_add(&master->node, &masters);
	list_add(&adev->node, &aggregate_devices);

	ret = try_to_bring_up_master(master, NULL);
	ret = try_to_bring_up_aggregate_device(adev, NULL);

	if (ret < 0)
		free_master(master);
		free_aggregate_device(adev);

	mutex_unlock(&component_mutex);

@@ -503,25 +557,25 @@ EXPORT_SYMBOL_GPL(component_master_add_with_match);
void component_master_del(struct device *parent,
	const struct component_master_ops *ops)
{
	struct master *master;
	struct aggregate_device *adev;

	mutex_lock(&component_mutex);
	master = __master_find(parent, ops);
	if (master) {
		take_down_master(master);
		free_master(master);
	adev = __aggregate_find(parent, ops);
	if (adev) {
		take_down_aggregate_device(adev);
		free_aggregate_device(adev);
	}
	mutex_unlock(&component_mutex);
}
EXPORT_SYMBOL_GPL(component_master_del);

static void component_unbind(struct component *component,
	struct master *master, void *data)
	struct aggregate_device *adev, void *data)
{
	WARN_ON(!component->bound);

	if (component->ops && component->ops->unbind)
		component->ops->unbind(component->dev, master->parent, data);
		component->ops->unbind(component->dev, adev->parent, data);
	component->bound = false;

	/* Release all resources claimed in the binding of this component */
@@ -539,26 +593,26 @@ static void component_unbind(struct component *component,
 */
void component_unbind_all(struct device *parent, void *data)
{
	struct master *master;
	struct aggregate_device *adev;
	struct component *c;
	size_t i;

	WARN_ON(!mutex_is_locked(&component_mutex));

	master = __master_find(parent, NULL);
	if (!master)
	adev = __aggregate_find(parent, NULL);
	if (!adev)
		return;

	/* Unbind components in reverse order */
	for (i = master->match->num; i--; )
		if (!master->match->compare[i].duplicate) {
			c = master->match->compare[i].component;
			component_unbind(c, master, data);
	for (i = adev->match->num; i--; )
		if (!adev->match->compare[i].duplicate) {
			c = adev->match->compare[i].component;
			component_unbind(c, adev, data);
		}
}
EXPORT_SYMBOL_GPL(component_unbind_all);

static int component_bind(struct component *component, struct master *master,
static int component_bind(struct component *component, struct aggregate_device *adev,
	void *data)
{
	int ret;
@@ -568,7 +622,7 @@ static int component_bind(struct component *component, struct master *master,
	 * This allows us to roll-back a failed component without
	 * affecting anything else.
	 */
	if (!devres_open_group(master->parent, NULL, GFP_KERNEL))
	if (!devres_open_group(adev->parent, NULL, GFP_KERNEL))
		return -ENOMEM;

	/*
@@ -577,14 +631,14 @@ static int component_bind(struct component *component, struct master *master,
	 * at the appropriate moment.
	 */
	if (!devres_open_group(component->dev, component, GFP_KERNEL)) {
		devres_release_group(master->parent, NULL);
		devres_release_group(adev->parent, NULL);
		return -ENOMEM;
	}

	dev_dbg(master->parent, "binding %s (ops %ps)\n",
	dev_dbg(adev->parent, "binding %s (ops %ps)\n",
		dev_name(component->dev), component->ops);

	ret = component->ops->bind(component->dev, master->parent, data);
	ret = component->ops->bind(component->dev, adev->parent, data);
	if (!ret) {
		component->bound = true;

@@ -595,16 +649,16 @@ static int component_bind(struct component *component, struct master *master,
		 * can clean those resources up independently.
		 */
		devres_close_group(component->dev, NULL);
		devres_remove_group(master->parent, NULL);
		devres_remove_group(adev->parent, NULL);

		dev_info(master->parent, "bound %s (ops %ps)\n",
		dev_info(adev->parent, "bound %s (ops %ps)\n",
			 dev_name(component->dev), component->ops);
	} else {
		devres_release_group(component->dev, NULL);
		devres_release_group(master->parent, NULL);
		devres_release_group(adev->parent, NULL);

		if (ret != -EPROBE_DEFER)
			dev_err(master->parent, "failed to bind %s (ops %ps): %d\n",
			dev_err(adev->parent, "failed to bind %s (ops %ps): %d\n",
				dev_name(component->dev), component->ops, ret);
	}

@@ -622,31 +676,31 @@ static int component_bind(struct component *component, struct master *master,
 */
int component_bind_all(struct device *parent, void *data)
{
	struct master *master;
	struct aggregate_device *adev;
	struct component *c;
	size_t i;
	int ret = 0;

	WARN_ON(!mutex_is_locked(&component_mutex));

	master = __master_find(parent, NULL);
	if (!master)
	adev = __aggregate_find(parent, NULL);
	if (!adev)
		return -EINVAL;

	/* Bind components in match order */
	for (i = 0; i < master->match->num; i++)
		if (!master->match->compare[i].duplicate) {
			c = master->match->compare[i].component;
			ret = component_bind(c, master, data);
	for (i = 0; i < adev->match->num; i++)
		if (!adev->match->compare[i].duplicate) {
			c = adev->match->compare[i].component;
			ret = component_bind(c, adev, data);
			if (ret)
				break;
		}

	if (ret != 0) {
		for (; i > 0; i--)
			if (!master->match->compare[i - 1].duplicate) {
				c = master->match->compare[i - 1].component;
				component_unbind(c, master, data);
			if (!adev->match->compare[i - 1].duplicate) {
				c = adev->match->compare[i - 1].component;
				component_unbind(c, adev, data);
			}
	}

@@ -675,8 +729,8 @@ static int __component_add(struct device *dev, const struct component_ops *ops,

	ret = try_to_bring_up_masters(component);
	if (ret < 0) {
		if (component->master)
			remove_component(component->master, component);
		if (component->adev)
			remove_component(component->adev, component);
		list_del(&component->node);

		kfree(component);
@@ -757,9 +811,9 @@ void component_del(struct device *dev, const struct component_ops *ops)
			break;
		}

	if (component && component->master) {
		take_down_master(component->master);
		remove_component(component->master, component);
	if (component && component->adev) {
		take_down_aggregate_device(component->adev);
		remove_component(component->adev, component);
	}

	mutex_unlock(&component_mutex);
+34 −54

File changed.

Preview size limit exceeded, changes collapsed.

+2 −2
Original line number Diff line number Diff line
@@ -692,7 +692,7 @@ EXPORT_SYMBOL_GPL(devres_release_group);

/*
 * Custom devres actions allow inserting a simple function call
 * into the teadown sequence.
 * into the teardown sequence.
 */

struct action_devres {
@@ -916,7 +916,7 @@ void *devm_krealloc(struct device *dev, void *ptr, size_t new_size, gfp_t gfp)

	/*
	 * We can copy the memory contents after releasing the lock as we're
	 * no longer modyfing the list links.
	 * no longer modifying the list links.
	 */
	memcpy(new_dr->data, old_dr->data,
	       total_old_size - offsetof(struct devres, data));
Loading