From patchwork Fri Oct 18 12:26:46 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lee Jones X-Patchwork-Id: 176821 Delivered-To: patch@linaro.org Received: by 2002:a92:7e96:0:0:0:0:0 with SMTP id q22csp791053ill; Fri, 18 Oct 2019 05:29:04 -0700 (PDT) X-Google-Smtp-Source: APXvYqxGQbD+0IDPtrQ+fv2SPGKWAqUsPPiUepsSq6EReX/RysD6zrjiyBVxB6dhzxrx5l4QHHis X-Received: by 2002:a17:906:160f:: with SMTP id m15mr8097743ejd.217.1571401744525; Fri, 18 Oct 2019 05:29:04 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1571401744; cv=none; d=google.com; s=arc-20160816; b=JBjNOtHcIO/uJL5osn1++FPC6kOnUIdUojccIbOf//OfQ5goi3r2jWPp46cR7KzX+0 TT0UWJehm6DkJPwd0jQIfbv0jAVKT/9cl+AlvMxh7qGVJPtlCXJWypi87ogxkswXTblG z7hJAAUPG6h0uVQhTU3EuO/AjAChNfdNqdGLVxmJKQsNl7txDa+os362wvBXEBs3W1fF NRFRU5/e07ho7WvBKuwZ1bVTqswV7ac6MHTzopNjy00T/aNH0NikNNLYJl3gqC4QpoNI 76agL4IKZRvb6MFUkcOQHaimxRQi/iZ9xVIvyiwuw4PiZyMMZEBUYFy12iW0C3duphXz MsQw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature; bh=lPeqEV+lINM78OOoyJTygefplPrg9vOEAay6eoGa0zY=; b=Mxn8Yj5aewk+u8sqAi5rz7iyRXj9PHlYA1Hfsg/B6Tz/taqUURc6ekg+I++ZiIUYwH CS6blIrb+YE3MneeT+I9JqbwuTXte59wouTA0Jcle25T2/u9eBhEEseyOjc6qCDZrYKH 1Z4ICBDEwPEeqijgOVYCLtpwmOyOdscrNNViHbcRX9c8Gc5MaPNYueQbs2eh+cj3itU5 hvpp4z24N9n7MELq0jqpub3UdHV6GoAbBhVKP5WskacOS3fLtz4ZxT6+PRp+plo11rnk PszzVkXNP2Us247sUahhQ2HJTeawNWUVpEQNvVU5qQjgXPEEOFlCScpH8atolhJLlh4r bsbQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=U5pZ1Wzg; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id a53si3957935edc.175.2019.10.18.05.29.04; Fri, 18 Oct 2019 05:29:04 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=U5pZ1Wzg; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2408010AbfJRM3D (ORCPT + 26 others); Fri, 18 Oct 2019 08:29:03 -0400 Received: from mail-wr1-f66.google.com ([209.85.221.66]:44700 "EHLO mail-wr1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2407925AbfJRM3B (ORCPT ); Fri, 18 Oct 2019 08:29:01 -0400 Received: by mail-wr1-f66.google.com with SMTP id z9so6046021wrl.11 for ; Fri, 18 Oct 2019 05:28:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=lPeqEV+lINM78OOoyJTygefplPrg9vOEAay6eoGa0zY=; b=U5pZ1Wzg42CoBwAgbqVmeQiaHcABrgHwn+lnnzgxyLfwzL15Ktp2HgdFDTgN04RlrC IvP0JqEptUYJWWPlVUvXfZD+bgjWjdjhaeGjTxd55fePxURwUU+bB1PxvMZtfLEYLGSg DLGLc1LeWcQ4C1m4uBpNstJI1T2l6T4Na0/be5K9E2JXn/vuZYFC70s1nc1Y8NYU1FRw UI5ERVAKaTV3L07XCM+pijgqQyvd1yF4WpTmkwj2lfwMyX0QCbv/1BlU5aNY/v/fEAE8 FTLuaTMEzJIzTdFzj0buvCfccirxXIqLEkWAtGH/qYDy9HHeyA5UDwPiZjxHXHzRJASz qhfw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=lPeqEV+lINM78OOoyJTygefplPrg9vOEAay6eoGa0zY=; b=GWWhSMBOpvVXm9/Ivrt7GmlyMcBWzSvO4NpU2WfQl7IOV8HgvtLUoa+0S5K0b7WAJe A80Jk6E2owAlRJ7DtWz/ijhBjVAOiTQ9kwruImDTQ9QOl52Ynx2ytlRCj4zMriO1jgCh XD3QwVlZa+SRaapXFgjkPjsPoJIR34HjTw+w6uNyci9bfx7Z5RnRanJCVrWHsjiE6qu2 uT+uT78RQxwcbPT0cTk8/vpM7pRZcP5bcn41qIxu6qtwfuIq3lrJV0MIhQl0wWxsuOPF ofKaZjggTeees7locWiypf4ccSNbfkbvupwy19HUAvF5DPdrnOqe+8QAS9bLCrvdviLZ OiFQ== X-Gm-Message-State: APjAAAXQ797tRc3pZcfNk/PvJvQzrH9tqFE/UFJN8Mtnles3ISSZU7bS JqHqbcOpf2icv4cLjrouTe0Zmw== X-Received: by 2002:adf:c641:: with SMTP id u1mr7714422wrg.361.1571401738224; Fri, 18 Oct 2019 05:28:58 -0700 (PDT) Received: from localhost.localdomain ([95.149.164.47]) by smtp.gmail.com with ESMTPSA id e3sm5033820wme.39.2019.10.18.05.28.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 18 Oct 2019 05:28:57 -0700 (PDT) From: Lee Jones To: broonie@kernel.org, linus.walleij@linaro.org, daniel.thompson@linaro.org, arnd@arndb.de Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, baohua@kernel.org, stephan@gerhold.net, Lee Jones Subject: [PATCH 1/2] mfd: mfd-core: Allocate reference counting memory directly to the platform device Date: Fri, 18 Oct 2019 13:26:46 +0100 Message-Id: <20191018122647.3849-2-lee.jones@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20191018122647.3849-1-lee.jones@linaro.org> References: <20191018122647.3849-1-lee.jones@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org MFD provides reference counting (for the 2 consumers who actually use it!) via mfd_cell's 'usage_count' member. However, since MFD cells become read-only (const), MFD needs to allocate writable memory and assign it to 'usage_count' before first registration. It currently does this by allocating enough memory for all requested child devices (yes, even disabled ones - but we'll get to that) and assigning the base pointer plus sub-device index to each device in the cell. The difficulty comes when trying to free that memory. During the removal of the parent device, MFD unregisters each child device, keeping a tally on the lowest memory location pointed to by a child device's 'usage_count'. Once all of the children are unregistered, the lowest memory location must be the base address of the previously allocated array, right? Well yes, until we try to honour the disabling of devices via Device Tree for instance. If the first child device in the provided batch is disabled, simply skipping registration (and consequentially deregistration) will mean that the first device's 'usage_count' pointer will not be accounted for when attempting to find the base. In which case, MFD will assume the first non- disabled 'usage_count' pointer is the base and subsequently attempt to erroneously free it. We can avoid all of this hoop jumping by simply allocating memory to each single child device before it is considered read-only. We can then free it on a per-device basis during deregistration. Signed-off-by: Lee Jones --- drivers/mfd/mfd-core.c | 42 ++++++++++++++++++------------------------ 1 file changed, 18 insertions(+), 24 deletions(-) -- 2.17.1 diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index 23276a80e3b4..eafdadd58e8b 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c @@ -61,9 +61,10 @@ int mfd_cell_disable(struct platform_device *pdev) EXPORT_SYMBOL(mfd_cell_disable); static int mfd_platform_add_cell(struct platform_device *pdev, - const struct mfd_cell *cell, - atomic_t *usage_count) + const struct mfd_cell *cell) { + atomic_t *usage_count; + if (!cell) return 0; @@ -71,7 +72,14 @@ static int mfd_platform_add_cell(struct platform_device *pdev, if (!pdev->mfd_cell) return -ENOMEM; + usage_count = kcalloc(1, sizeof(*usage_count), GFP_KERNEL); + if (!usage_count) { + kfree(pdev->mfd_cell); + return -ENOMEM; + } + pdev->mfd_cell->usage_count = usage_count; + return 0; } @@ -134,7 +142,7 @@ static inline void mfd_acpi_add_device(const struct mfd_cell *cell, #endif static int mfd_add_device(struct device *parent, int id, - const struct mfd_cell *cell, atomic_t *usage_count, + const struct mfd_cell *cell, struct resource *mem_base, int irq_base, struct irq_domain *domain) { @@ -196,7 +204,7 @@ static int mfd_add_device(struct device *parent, int id, goto fail_alias; } - ret = mfd_platform_add_cell(pdev, cell, usage_count); + ret = mfd_platform_add_cell(pdev, cell); if (ret) goto fail_alias; @@ -286,16 +294,9 @@ int mfd_add_devices(struct device *parent, int id, { int i; int ret; - atomic_t *cnts; - - /* initialize reference counting for all cells */ - cnts = kcalloc(n_devs, sizeof(*cnts), GFP_KERNEL); - if (!cnts) - return -ENOMEM; for (i = 0; i < n_devs; i++) { - atomic_set(&cnts[i], 0); - ret = mfd_add_device(parent, id, cells + i, cnts + i, mem_base, + ret = mfd_add_device(parent, id, cells + i, mem_base, irq_base, domain); if (ret) goto fail; @@ -306,17 +307,15 @@ int mfd_add_devices(struct device *parent, int id, fail: if (i) mfd_remove_devices(parent); - else - kfree(cnts); + return ret; } EXPORT_SYMBOL(mfd_add_devices); -static int mfd_remove_devices_fn(struct device *dev, void *c) +static int mfd_remove_devices_fn(struct device *dev, void *data) { struct platform_device *pdev; const struct mfd_cell *cell; - atomic_t **usage_count = c; if (dev->type != &mfd_dev_type) return 0; @@ -327,9 +326,7 @@ static int mfd_remove_devices_fn(struct device *dev, void *c) regulator_bulk_unregister_supply_alias(dev, cell->parent_supplies, cell->num_parent_supplies); - /* find the base address of usage_count pointers (for freeing) */ - if (!*usage_count || (cell->usage_count < *usage_count)) - *usage_count = cell->usage_count; + kfree(cell->usage_count); platform_device_unregister(pdev); return 0; @@ -337,10 +334,7 @@ static int mfd_remove_devices_fn(struct device *dev, void *c) void mfd_remove_devices(struct device *parent) { - atomic_t *cnts = NULL; - - device_for_each_child_reverse(parent, &cnts, mfd_remove_devices_fn); - kfree(cnts); + device_for_each_child_reverse(parent, NULL, mfd_remove_devices_fn); } EXPORT_SYMBOL(mfd_remove_devices); @@ -404,7 +398,7 @@ int mfd_clone_cell(const char *cell, const char **clones, size_t n_clones) cell_entry.name = clones[i]; /* don't give up if a single call fails; just report error */ if (mfd_add_device(pdev->dev.parent, -1, &cell_entry, - cell_entry.usage_count, NULL, 0, NULL)) + NULL, 0, NULL)) dev_err(dev, "failed to create platform device '%s'\n", clones[i]); } From patchwork Fri Oct 18 12:26:47 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lee Jones X-Patchwork-Id: 176822 Delivered-To: patch@linaro.org Received: by 2002:a92:7e96:0:0:0:0:0 with SMTP id q22csp791152ill; Fri, 18 Oct 2019 05:29:09 -0700 (PDT) X-Google-Smtp-Source: APXvYqwph43fzeadgL3NWBT1tqaNOQ+0les/OCF7z45lKpE8r1mgorHF8JQAQU1GHgmz6puAx6uE X-Received: by 2002:a05:6402:1514:: with SMTP id f20mr9410022edw.35.1571401749745; Fri, 18 Oct 2019 05:29:09 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1571401749; cv=none; d=google.com; s=arc-20160816; b=gHnic6B4NQ5WUEUhP00bIFnOgERRNk2GYSvAmJMjgyNgV5C6k//EqX6iz0G6dRNbgi 2AdqVJek4Fh0t4hoMcdbcYnWYO90+Nfpod1LWVgGpdCxdgROZy9A90dK98qSlLTUfsQ9 kmiRe2y+231MsWfOSfb+O5COznuWaFN5NAqIdGbqreQGqSLk6NKMqXF0iF1/vCztckiM HkWFDwxMVP/eMSRc4GqbK3oUgdoOxj93X5AcSKzf7gp4vLHrkI7Cj2DKHFOLurOBnq7n 09C5ro2dgePzByz+Ctf225+xiy7v+Ma+g6SvzdwYLDDYWH7oTCsfC3eJ+zA5I3jdRbf6 awOw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature; bh=JOGbCAX9wvou6ywsxAyjFayUMg5QkjoPiWUMNf49UP4=; b=StMkM0NxXELdcZ3tBnY8Fpsnq5uTQ2k5YbKAE/DHWBzS3icqbaClaSPsMMG+AVebnS lKpThHKImkuvqGw6HI2dbCrrEu+9To1jR+H1rbLpQxK4hjb5Dnl117QThuvLgMf8sR9S zM1jkbT+KYg37+nb1rnHtIE/AsIPv1qS6ao1AAc4lOFlhDnV7crIIFLXHR8/tb2c1QDa /BHvGgvFcdpESZNTNJHg3VRc5V/gZKreM0auqGWLYhmZ/iAU/FOuMzG6r6ZzRi+TTGI6 Gk3VxAZU6SWFMfSq3ODMag5zdYrrXuGo6syDqDXoWafI8ecLHL1fFBchsdxyaNuaxDPP Cptg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=FHn4bQGU; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id r17si4032117edx.257.2019.10.18.05.29.09; Fri, 18 Oct 2019 05:29:09 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=FHn4bQGU; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2408046AbfJRM3F (ORCPT + 26 others); Fri, 18 Oct 2019 08:29:05 -0400 Received: from mail-wr1-f66.google.com ([209.85.221.66]:33936 "EHLO mail-wr1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2389585AbfJRM3C (ORCPT ); Fri, 18 Oct 2019 08:29:02 -0400 Received: by mail-wr1-f66.google.com with SMTP id t16so929676wrr.1 for ; Fri, 18 Oct 2019 05:28:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=JOGbCAX9wvou6ywsxAyjFayUMg5QkjoPiWUMNf49UP4=; b=FHn4bQGUrrme8bhdcuqbKlKd4iJXjl0H680Dwdil6m5suU5dWL94Fgcyp/05VQzwrM IpHa8A90edNgbxCwOirUmCs3KMllZWamn0ZPjdUit+YGXPGCn/AtWY/S0v2uCdwJBAFH U/vk2d8CtrJgbBYDu7xAQgLbdcILRIy9qqgMYzbHvLjL8pcImeWmPwFTEuku/0jxQsGY Om6RbYNvZZP5ddmrJKbFgHvMnAnM0XF12HW2K71fIqtA9pF8DXdf/MXGzkGXYgxn0M4j GYj7PJ0cCmn6SZJSBAAwc0eBtAuEgQIBBtX95N7/SJWTIJag3z7yfa+pa8tQrRyNwHH6 bn0A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=JOGbCAX9wvou6ywsxAyjFayUMg5QkjoPiWUMNf49UP4=; b=EA93BMhjkTyVprhItGEGwO92D7f6vVmS+tcZI9gkDHTMm8vxkT1Yz2gIskyUrkgT2+ zTQGwJ8GzkwUbQF8w0Y7xaot9zh0KBPAHZHvzZoFus14hKDQ7F02o/pxya+eZmXB5Xvl 5IkICRRXCgQ6pfFwHznXLXqdcvdY5tApPybtn3xYSLL2Vx/R8ljuCWQq8AkzXlCf9RUK Q077IzL3KC2pm3i9eiOJt1a6MVNt8jfxeR0oFrSscwS8z4as/D9GdqfxCpSSqg8ajiAd 0tyul5Pl3V64DTsMO5tQSUpuQVOubuJQwryKQJKxNeCJVtRb8RivudxDNBQg2dGRXThC oqEg== X-Gm-Message-State: APjAAAUkucyulXzRS/BD9iCzZMeBdqtYOf1lnHrCt8t+V5ylANlhCqTg +6nU4MUE9k1Ry1MqHsF1w2rL8w== X-Received: by 2002:a5d:522f:: with SMTP id i15mr7209770wra.257.1571401739165; Fri, 18 Oct 2019 05:28:59 -0700 (PDT) Received: from localhost.localdomain ([95.149.164.47]) by smtp.gmail.com with ESMTPSA id e3sm5033820wme.39.2019.10.18.05.28.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 18 Oct 2019 05:28:58 -0700 (PDT) From: Lee Jones To: broonie@kernel.org, linus.walleij@linaro.org, daniel.thompson@linaro.org, arnd@arndb.de Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, baohua@kernel.org, stephan@gerhold.net, Lee Jones Subject: [PATCH 2/2] mfd: mfd-core: Honour Device Tree's request to disable a child-device Date: Fri, 18 Oct 2019 13:26:47 +0100 Message-Id: <20191018122647.3849-3-lee.jones@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20191018122647.3849-1-lee.jones@linaro.org> References: <20191018122647.3849-1-lee.jones@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Until now, MFD has assumed all child devices passed to it (via mfd_cells) are to be registered. It does not take into account requests from Device Tree and the like to disable child devices on a per-platform basis. Well now it does. Reported-by: Barry Song Reported-by: Stephan Gerhold Signed-off-by: Lee Jones --- drivers/mfd/mfd-core.c | 5 +++++ 1 file changed, 5 insertions(+) -- 2.17.1 diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index eafdadd58e8b..24c139633524 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c @@ -182,6 +182,11 @@ static int mfd_add_device(struct device *parent, int id, if (parent->of_node && cell->of_compatible) { for_each_child_of_node(parent->of_node, np) { if (of_device_is_compatible(np, cell->of_compatible)) { + if (!of_device_is_available(np)) { + /* Ignore disabled devices error free */ + ret = 0; + goto fail_alias; + } pdev->dev.of_node = np; pdev->dev.fwnode = &np->fwnode; break;