aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-02-14 13:40:21 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2016-02-14 13:40:21 -0500
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,
206 if (mc->release) 206 if (mc->release)
207 mc->release(master, mc->data); 207 mc->release(master, mc->data);
208 } 208 }
209
210 kfree(match->compare);
209} 211}
210 212
211static void devm_component_match_release(struct device *dev, void *res) 213static void devm_component_match_release(struct device *dev, void *res)
@@ -221,14 +223,14 @@ static int component_match_realloc(struct device *dev,
221 if (match->alloc == num) 223 if (match->alloc == num)
222 return 0; 224 return 0;
223 225
224 new = devm_kmalloc_array(dev, num, sizeof(*new), GFP_KERNEL); 226 new = kmalloc_array(num, sizeof(*new), GFP_KERNEL);
225 if (!new) 227 if (!new)
226 return -ENOMEM; 228 return -ENOMEM;
227 229
228 if (match->compare) { 230 if (match->compare) {
229 memcpy(new, match->compare, sizeof(*new) * 231 memcpy(new, match->compare, sizeof(*new) *
230 min(match->num, num)); 232 min(match->num, num));
231 devm_kfree(dev, match->compare); 233 kfree(match->compare);
232 } 234 }
233 match->compare = new; 235 match->compare = new;
234 match->alloc = num; 236 match->alloc = num;
@@ -283,6 +285,24 @@ void component_match_add_release(struct device *master,
283} 285}
284EXPORT_SYMBOL(component_match_add_release); 286EXPORT_SYMBOL(component_match_add_release);
285 287
288static void free_master(struct master *master)
289{
290 struct component_match *match = master->match;
291 int i;
292
293 list_del(&master->node);
294
295 if (match) {
296 for (i = 0; i < match->num; i++) {
297 struct component *c = match->compare[i].component;
298 if (c)
299 c->master = NULL;
300 }
301 }
302
303 kfree(master);
304}
305
286int component_master_add_with_match(struct device *dev, 306int component_master_add_with_match(struct device *dev,
287 const struct component_master_ops *ops, 307 const struct component_master_ops *ops,
288 struct component_match *match) 308 struct component_match *match)
@@ -309,11 +329,9 @@ int component_master_add_with_match(struct device *dev,
309 329
310 ret = try_to_bring_up_master(master, NULL); 330 ret = try_to_bring_up_master(master, NULL);
311 331
312 if (ret < 0) { 332 if (ret < 0)
313 /* Delete off the list if we weren't successful */ 333 free_master(master);
314 list_del(&master->node); 334
315 kfree(master);
316 }
317 mutex_unlock(&component_mutex); 335 mutex_unlock(&component_mutex);
318 336
319 return ret < 0 ? ret : 0; 337 return ret < 0 ? ret : 0;
@@ -324,25 +342,12 @@ void component_master_del(struct device *dev,
324 const struct component_master_ops *ops) 342 const struct component_master_ops *ops)
325{ 343{
326 struct master *master; 344 struct master *master;
327 int i;
328 345
329 mutex_lock(&component_mutex); 346 mutex_lock(&component_mutex);
330 master = __master_find(dev, ops); 347 master = __master_find(dev, ops);
331 if (master) { 348 if (master) {
332 struct component_match *match = master->match;
333
334 take_down_master(master); 349 take_down_master(master);
335 350 free_master(master);
336 list_del(&master->node);
337
338 if (match) {
339 for (i = 0; i < match->num; i++) {
340 struct component *c = match->compare[i].component;
341 if (c)
342 c->master = NULL;
343 }
344 }
345 kfree(master);
346 } 351 }
347 mutex_unlock(&component_mutex); 352 mutex_unlock(&component_mutex);
348} 353}
@@ -486,6 +491,8 @@ int component_add(struct device *dev, const struct component_ops *ops)
486 491
487 ret = try_to_bring_up_masters(component); 492 ret = try_to_bring_up_masters(component);
488 if (ret < 0) { 493 if (ret < 0) {
494 if (component->master)
495 remove_component(component->master, component);
489 list_del(&component->node); 496 list_del(&component->node);
490 497
491 kfree(component); 498 kfree(component);