Commit 8b9f9ebe authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'component' of git://ftp.arm.linux.org.uk/~rmk/linux-arm

Pull component helper fixes from Russell King:
 "A few fixes for problems people have encountered with the recent
  update to the component helpers"

* 'component' of git://ftp.arm.linux.org.uk/~rmk/linux-arm:
  component: remove device from master match list on failed add
  component: Detach components when deleting master struct
  component: fix crash on x86_64 with hda audio drivers
parents 7686e3c1 8e7199c2
Loading
Loading
Loading
Loading
+28 −21
Original line number Diff line number Diff line
@@ -206,6 +206,8 @@ static void component_match_release(struct device *master,
		if (mc->release)
			mc->release(master, mc->data);
	}

	kfree(match->compare);
}

static void devm_component_match_release(struct device *dev, void *res)
@@ -221,14 +223,14 @@ static int component_match_realloc(struct device *dev,
	if (match->alloc == num)
		return 0;

	new = devm_kmalloc_array(dev, num, sizeof(*new), GFP_KERNEL);
	new = kmalloc_array(num, sizeof(*new), GFP_KERNEL);
	if (!new)
		return -ENOMEM;

	if (match->compare) {
		memcpy(new, match->compare, sizeof(*new) *
					    min(match->num, num));
		devm_kfree(dev, match->compare);
		kfree(match->compare);
	}
	match->compare = new;
	match->alloc = num;
@@ -283,6 +285,24 @@ void component_match_add_release(struct device *master,
}
EXPORT_SYMBOL(component_match_add_release);

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

	list_del(&master->node);

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

	kfree(master);
}

int component_master_add_with_match(struct device *dev,
	const struct component_master_ops *ops,
	struct component_match *match)
@@ -309,11 +329,9 @@ int component_master_add_with_match(struct device *dev,

	ret = try_to_bring_up_master(master, NULL);

	if (ret < 0) {
		/* Delete off the list if we weren't successful */
		list_del(&master->node);
		kfree(master);
	}
	if (ret < 0)
		free_master(master);

	mutex_unlock(&component_mutex);

	return ret < 0 ? ret : 0;
@@ -324,25 +342,12 @@ void component_master_del(struct device *dev,
	const struct component_master_ops *ops)
{
	struct master *master;
	int i;

	mutex_lock(&component_mutex);
	master = __master_find(dev, ops);
	if (master) {
		struct component_match *match = master->match;

		take_down_master(master);

		list_del(&master->node);

		if (match) {
			for (i = 0; i < match->num; i++) {
				struct component *c = match->compare[i].component;
				if (c)
					c->master = NULL;
			}
		}
		kfree(master);
		free_master(master);
	}
	mutex_unlock(&component_mutex);
}
@@ -486,6 +491,8 @@ 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);
		list_del(&component->node);

		kfree(component);