Message ID | 1453831153.2850.107.camel@linaro.org |
---|---|
State | New |
Headers | show |
On Tue, 2016-01-26 at 22:35 +0000, Russell King - ARM Linux wrote: > On Tue, Jan 26, 2016 at 05:59:13PM +0000, Jon Medhurst (Tixy) wrote: > > I believe I've found a problem with the component helpers and/or how > > drivers use them. I discovered this whilst trying to get ARM's HDLCD > > driver [1] working on 4.5-rc1, however I believe that code is following > > a pattern used by drivers already in 4.5 and the problem isn't specific > > to it. This is what I have observed... > > Hmm, it all looks plausible, and I'm again left wondering how the code > passed testing over the last year (I've been running this code for > ages both on iMX6 and Dove, where deferred probing does happen.) It depends on the order of things. To go wrong, components must already be there before the master is added, then the master needs to defer probing from it's bind callback. So, components deferring won't trigger the issue, neither will master deferring before any components have been added. > Your patch looks like the right thing to do, so I'll add it to the > component tree shortly - it should end up in linux-next in a few days > time. Thanks. I wasn't sure if that patch was correct as I hadn't looked at any of this code before this week. -- Tixy _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
On Wed, 2016-01-27 at 09:18 +0000, Jon Medhurst (Tixy) wrote: > On Tue, 2016-01-26 at 22:35 +0000, Russell King - ARM Linux wrote: > > On Tue, Jan 26, 2016 at 05:59:13PM +0000, Jon Medhurst (Tixy) wrote: > > > I believe I've found a problem with the component helpers and/or how > > > drivers use them. I discovered this whilst trying to get ARM's HDLCD > > > driver [1] working on 4.5-rc1, however I believe that code is following > > > a pattern used by drivers already in 4.5 and the problem isn't specific > > > to it. This is what I have observed... > > > > Hmm, it all looks plausible, and I'm again left wondering how the code > > passed testing over the last year (I've been running this code for > > ages both on iMX6 and Dove, where deferred probing does happen.) > > It depends on the order of things. To go wrong, components must already > be there before the master is added, then the master needs to defer > probing from it's bind callback. So, components deferring won't trigger > the issue, Actually, looks like drm drivers for armada and imx will end up calling component_bind_all from their bind callpath, so if components return -EPROBE_DEFER from their bind function, then the master will bail out with that, triggering my failure scenario. Hmmm... -- Tixy _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
diff --git a/drivers/base/component.c b/drivers/base/component.c index 89f5cf68..a3a1394 100644 --- a/drivers/base/component.c +++ b/drivers/base/component.c @@ -283,6 +283,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 +327,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 +340,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); }