From patchwork Fri Nov 29 14:04:46 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Sebastian Andrzej Siewior X-Patchwork-Id: 1202486 Return-Path: X-Original-To: incoming-dt@patchwork.ozlabs.org Delivered-To: patchwork-incoming-dt@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=devicetree-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=linutronix.de Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 47PbqP42fWz9sRK for ; Sat, 30 Nov 2019 01:04:49 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726808AbfK2OEs convert rfc822-to-8bit (ORCPT ); Fri, 29 Nov 2019 09:04:48 -0500 Received: from Galois.linutronix.de ([193.142.43.55]:48868 "EHLO Galois.linutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726763AbfK2OEs (ORCPT ); Fri, 29 Nov 2019 09:04:48 -0500 Received: from bigeasy by Galois.linutronix.de with local (Exim 4.80) (envelope-from ) id 1iagt4-0007ze-5d; Fri, 29 Nov 2019 15:04:46 +0100 Date: Fri, 29 Nov 2019 15:04:46 +0100 From: Sebastian Andrzej Siewior To: Frank Rowand Cc: devicetree@vger.kernel.org, Rob Herring , Thomas Gleixner Subject: [PATCH v2] of: allocate / free phandle cache outside of the devtree_lock Message-ID: <20191129140446.dqb5y4uzv57cislp@linutronix.de> References: <20191111172142.ozczh7j2gmzi7o5k@linutronix.de> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org The phandle cache code allocates memory while holding devtree_lock which is a raw_spinlock_t. Memory allocation (and free()) is not possible on RT while a raw_spinlock_t is held. Invoke the kfree() and kcalloc() while the lock is dropped. Cc: Rob Herring Cc: Frank Rowand Cc: devicetree@vger.kernel.org Signed-off-by: Sebastian Andrzej Siewior Reviewed-by: Frank Rowand --- v1…v2: - Add comments regarding memory allocation under the raw_spinlock_t - use a temporary variable for the memory allocation. drivers/of/base.c | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -136,33 +136,37 @@ static struct device_node **phandle_cach static u32 phandle_cache_mask; /* - * Caller must hold devtree_lock. + * Caller must hold devtree_lock under which kfree() can't be used so caller + * needs to kfree() the returned pointer. */ -static void __of_free_phandle_cache(void) +static struct device_node **__of_free_phandle_cache(void) { u32 cache_entries = phandle_cache_mask + 1; u32 k; + struct device_node **shadow; if (!phandle_cache) - return; + return NULL; for (k = 0; k < cache_entries; k++) of_node_put(phandle_cache[k]); - kfree(phandle_cache); + shadow = phandle_cache; phandle_cache = NULL; + return shadow; } int of_free_phandle_cache(void) { unsigned long flags; + struct device_node **shadow; raw_spin_lock_irqsave(&devtree_lock, flags); - __of_free_phandle_cache(); + shadow = __of_free_phandle_cache(); raw_spin_unlock_irqrestore(&devtree_lock, flags); - + kfree(shadow); return 0; } #if !defined(CONFIG_MODULES) @@ -197,10 +201,12 @@ void of_populate_phandle_cache(void) u32 cache_entries; struct device_node *np; u32 phandles = 0; + struct device_node **shadow; + struct device_node **tmp_phandle_cache; raw_spin_lock_irqsave(&devtree_lock, flags); - __of_free_phandle_cache(); + shadow = __of_free_phandle_cache(); for_each_of_allnodes(np) if (np->phandle && np->phandle != OF_PHANDLE_ILLEGAL) @@ -208,12 +214,19 @@ void of_populate_phandle_cache(void) if (!phandles) goto out; + /* + * kcalloc() can't be used while a raw_spinlock_t held so it is dropped + * for the allocation. + */ + raw_spin_unlock_irqrestore(&devtree_lock, flags); cache_entries = roundup_pow_of_two(phandles); phandle_cache_mask = cache_entries - 1; - phandle_cache = kcalloc(cache_entries, sizeof(*phandle_cache), - GFP_ATOMIC); + tmp_phandle_cache = kcalloc(cache_entries, sizeof(*phandle_cache), + GFP_ATOMIC); + raw_spin_lock_irqsave(&devtree_lock, flags); + phandle_cache = tmp_phandle_cache; if (!phandle_cache) goto out; @@ -225,6 +238,7 @@ void of_populate_phandle_cache(void) out: raw_spin_unlock_irqrestore(&devtree_lock, flags); + kfree(shadow); } void __init of_core_init(void)