diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-02-14 13:40:21 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-02-14 13:40:21 -0500 |
commit | 8b9f9ebe07f4ff1340f44e40aa7ce517d55e1882 (patch) | |
tree | e091716549151b74679154ce8952b3ca30306a8d | |
parent | 7686e3c16c4a3669472298ecfc4636485658642b (diff) | |
parent | 8e7199c2c50fff1969302643171eaa33f1ca148f (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.c | 49 |
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 | ||
211 | static void devm_component_match_release(struct device *dev, void *res) | 213 | static 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 | } |
284 | EXPORT_SYMBOL(component_match_add_release); | 286 | EXPORT_SYMBOL(component_match_add_release); |
285 | 287 | ||
288 | static 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 | |||
286 | int component_master_add_with_match(struct device *dev, | 306 | int 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); |