From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S642759AbdD1WDZ (ORCPT ); Fri, 28 Apr 2017 18:03:25 -0400 Received: from mail-yw0-f194.google.com ([209.85.161.194]:35763 "EHLO mail-yw0-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2993742AbdD1WDW (ORCPT ); Fri, 28 Apr 2017 18:03:22 -0400 Date: Fri, 28 Apr 2017 18:03:14 -0400 From: Tejun Heo To: Andre Przywara Cc: Icenowy Zheng , Greg Kroah-Hartman , Adam Borowski , "linux-kernel@vger.kernel.org" Subject: Re: sun50i-a64-pinctrl WARN_ON drivers/base/dd.c:349 Message-ID: <20170428220314.GI22354@htj.duckdns.org> References: <20170315161406.smd4na25two55jjh@angband.pl> <197431489595078@web8g.yandex.ru> <20170316010615.GA23552@kroah.com> <20170317140812.GB5078@htj.duckdns.org> <785901489760914@web50g.yandex.ru> <20170317144422.GD5078@htj.duckdns.org> <3cf02066-ca0e-05f4-6a3d-ebc6d5373caf@arm.com> <20170418072505.GE3899@wtj.duckdns.org> <3fda46eb-7fcc-4c27-98b6-7d822cce1405@arm.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <3fda46eb-7fcc-4c27-98b6-7d822cce1405@arm.com> User-Agent: Mutt/1.8.0 (2017-02-23) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hello, On Tue, Apr 18, 2017 at 10:12:16AM +0100, Andre Przywara wrote: > Yeah, so I stack-dumped on the zero allocations and indeed they are > called from cleanup functions: > drivers/pinctrl/pinmux.c:pinmux_generic_free_functions(): > devm_kzalloc(sizeof(*indices) * pctldev->num_functions, ...) > (and another one I don't know from the top of the my head, logs at home) > > So my hunch was that once EPROBE_DEFER triggers the devres cleanup, it > uses some reverse list traversal to release all allocated resources > (backwards!), so missing those which get (appended) during the process. > But I don't think that would not work with the locking. > So I have to dig deeper tonight in my logs. If this is a valid use case, we can change devm to repeat till empty but it's a weird thing to do to allocate from a release function. So, something like this. Only compile tested. Thanks. diff --git a/drivers/base/devres.c b/drivers/base/devres.c index 71d5770..d2a9f34 100644 --- a/drivers/base/devres.c +++ b/drivers/base/devres.c @@ -509,13 +509,21 @@ static int release_nodes(struct device *dev, struct list_head *first, int devres_release_all(struct device *dev) { unsigned long flags; + int cnt = 0, ret; /* Looks like an uninitialized device structure */ if (WARN_ON(dev->devres_head.next == NULL)) return -ENODEV; - spin_lock_irqsave(&dev->devres_lock, flags); - return release_nodes(dev, dev->devres_head.next, &dev->devres_head, - flags); + + /* Release callbacks may create new nodes, repeat till empty */ + do { + spin_lock_irqsave(&dev->devres_lock, flags); + ret = release_nodes(dev, dev->devres_head.next, + &dev->devres_head, flags); + cnt += ret; + } while (ret); + + return cnt; } /**