summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-02-14 10:40:21 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2016-02-14 10:40:21 -0800
commit8b9f9ebe07f4ff1340f44e40aa7ce517d55e1882 (patch)
treee091716549151b74679154ce8952b3ca30306a8d
parent7686e3c16c4a3669472298ecfc4636485658642b (diff)
parent8e7199c2c50fff1969302643171eaa33f1ca148f (diff)
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
-rw-r--r--drivers/base/component.c49
1 files changed, 28 insertions, 21 deletions
diff --git a/drivers/base/component.c b/drivers/base/component.c
index 89f5cf68d80a..04a1582e80bb 100644
--- a/drivers/base/component.c
+++ b/drivers/base/component.c
@@ -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);