From patchwork Wed Jul 23 23:44:18 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Grant Likely X-Patchwork-Id: 34187 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-oi0-f70.google.com (mail-oi0-f70.google.com [209.85.218.70]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id DB12420672 for ; Wed, 23 Jul 2014 23:47:37 +0000 (UTC) Received: by mail-oi0-f70.google.com with SMTP id u20sf7326992oif.9 for ; Wed, 23 Jul 2014 16:47:37 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:sender:precedence:list-id :x-original-sender:x-original-authentication-results:mailing-list :list-post:list-help:list-archive:list-unsubscribe; bh=LO932DN1bQ5kTW3e0nUAyGS6uTenmee451tHItlbM28=; b=a2+Dhn+gQfTMtoLchuUuSZzidUpKf4yrcVPol0s5NDYhGMclIPd0qMI1HG10aGmLsk jwB17ekV1/wi4wgReFAaPNdGJ4nm0c7eJvWuyjXN9lo4FaqU0RIVkkwvFoSopdMtQgEe 8P0J9sMyJu+gJ9rc9UA9qj2rn0ijzmQ3h8vXdGYDmzDzlJyCl3U1T+YJJ1L/tLSylI+b JjFrhSouvdj+0g3QBHByrEDvsuXJFZLd0qZg9e0mxaCRqGsscc50qqG3H1jj+AkGQbnG TlLcsWVez1lPabP0x1edieqYnbfysBEu+FIE3PBJ1VWVTfwXlQj6xQg5Av5wrtbAqtKX lfkQ== X-Gm-Message-State: ALoCoQmtFbHY1NwPYqIGrM1NpL8bXXSLWwK4gDjNWs0+ncskBHnecm9NQiAQrAzzDXG7zNs9lUl7 X-Received: by 10.182.66.33 with SMTP id c1mr2342168obt.39.1406159257403; Wed, 23 Jul 2014 16:47:37 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.41.82 with SMTP id y76ls522063qgy.75.gmail; Wed, 23 Jul 2014 16:47:37 -0700 (PDT) X-Received: by 10.52.24.68 with SMTP id s4mr5701858vdf.37.1406159257302; Wed, 23 Jul 2014 16:47:37 -0700 (PDT) Received: from mail-vc0-f173.google.com (mail-vc0-f173.google.com [209.85.220.173]) by mx.google.com with ESMTPS id c14si3806951vej.48.2014.07.23.16.47.37 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 23 Jul 2014 16:47:37 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.173 as permitted sender) client-ip=209.85.220.173; Received: by mail-vc0-f173.google.com with SMTP id hy10so3618550vcb.18 for ; Wed, 23 Jul 2014 16:47:37 -0700 (PDT) X-Received: by 10.52.129.200 with SMTP id ny8mr5827787vdb.27.1406159257215; Wed, 23 Jul 2014 16:47:37 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.221.37.5 with SMTP id tc5csp321095vcb; Wed, 23 Jul 2014 16:47:36 -0700 (PDT) X-Received: by 10.68.95.225 with SMTP id dn1mr6014191pbb.126.1406159256125; Wed, 23 Jul 2014 16:47:36 -0700 (PDT) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id zw4si4020303pbc.241.2014.07.23.16.47.35 for ; Wed, 23 Jul 2014 16:47:36 -0700 (PDT) Received-SPF: none (google.com: devicetree-owner@vger.kernel.org does not designate permitted sender hosts) client-ip=209.132.180.67; Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758553AbaGWXre (ORCPT + 7 others); Wed, 23 Jul 2014 19:47:34 -0400 Received: from mail-pa0-f41.google.com ([209.85.220.41]:43643 "EHLO mail-pa0-f41.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1758545AbaGWXog (ORCPT ); Wed, 23 Jul 2014 19:44:36 -0400 Received: by mail-pa0-f41.google.com with SMTP id rd3so2678767pab.28 for ; Wed, 23 Jul 2014 16:44:35 -0700 (PDT) X-Received: by 10.70.55.229 with SMTP id v5mr5830876pdp.145.1406159075652; Wed, 23 Jul 2014 16:44:35 -0700 (PDT) Received: from trevor.secretlab.ca (S0106602ad082623c.cg.shawcable.net. [68.146.69.61]) by mx.google.com with ESMTPSA id og3sm3558075pbc.48.2014.07.23.16.44.33 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 23 Jul 2014 16:44:33 -0700 (PDT) Received: by trevor.secretlab.ca (Postfix, from userid 1000) id CE576C439EA; Wed, 23 Jul 2014 17:44:26 -0600 (MDT) From: Grant Likely To: linux-kernel@vger.kernel.org, Nathan Fontenot , Tyrel Datwyler , Pantelis Antoniou , devicetree@vger.kernel.org Cc: Grant Likely Subject: [PATCH 04/10] OF: Utility helper functions for dynamic nodes Date: Wed, 23 Jul 2014 17:44:18 -0600 Message-Id: <1406159064-21366-5-git-send-email-grant.likely@linaro.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1406159064-21366-1-git-send-email-grant.likely@linaro.org> References: <1406159064-21366-1-git-send-email-grant.likely@linaro.org> Sender: devicetree-owner@vger.kernel.org Precedence: list List-ID: X-Mailing-List: devicetree@vger.kernel.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: grant.likely@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.173 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , From: Pantelis Antoniou Introduce helper functions for working with the live DT tree, all of them related to dynamically adding/removing nodes and properties. __of_prop_dup() copies a property dynamically __of_node_alloc() creates an empty node Bug fix about prop->len == 0 by Ionut Nicu Signed-off-by: Pantelis Antoniou [glikely: Added unittest for of_copy_property and dropped fine-grained allocations] [glikely: removed name, type and phandle arguments from __of_node_alloc] Signed-off-by: Grant Likely --- drivers/of/dynamic.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++ drivers/of/of_private.h | 10 +++++++ drivers/of/selftest.c | 28 ++++++++++++++++++ 3 files changed, 115 insertions(+) diff --git a/drivers/of/dynamic.c b/drivers/of/dynamic.c index 125994330437..e0c4c6e25980 100644 --- a/drivers/of/dynamic.c +++ b/drivers/of/dynamic.c @@ -214,3 +214,80 @@ void of_node_release(struct kobject *kobj) kfree(node->data); kfree(node); } + +/** + * __of_prop_dup - Copy a property dynamically. + * @prop: Property to copy + * @allocflags: Allocation flags (typically pass GFP_KERNEL) + * + * Copy a property by dynamically allocating the memory of both the + * property stucture and the property name & contents. The property's + * flags have the OF_DYNAMIC bit set so that we can differentiate between + * dynamically allocated properties and not. + * Returns the newly allocated property or NULL on out of memory error. + */ +struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags) +{ + struct property *new; + + new = kzalloc(sizeof(*new), allocflags); + if (!new) + return NULL; + + /* + * NOTE: There is no check for zero length value. + * In case of a boolean property This will allocate a value + * of zero bytes. We do this to work around the use + * of of_get_property() calls on boolean values. + */ + new->name = kstrdup(prop->name, allocflags); + new->value = kmemdup(prop->value, prop->length, allocflags); + new->length = prop->length; + if (!new->name || !new->value) + goto err_free; + + /* mark the property as dynamic */ + of_property_set_flag(new, OF_DYNAMIC); + + return new; + + err_free: + kfree(new->name); + kfree(new->value); + kfree(new); + return NULL; +} + +/** + * __of_node_alloc() - Create an empty device node dynamically. + * @full_name: Full name of the new device node + * @allocflags: Allocation flags (typically pass GFP_KERNEL) + * + * Create an empty device tree node, suitable for further modification. + * The node data are dynamically allocated and all the node flags + * have the OF_DYNAMIC & OF_DETACHED bits set. + * Returns the newly allocated node or NULL on out of memory error. + */ +struct device_node *__of_node_alloc(const char *full_name, gfp_t allocflags) +{ + struct device_node *node; + + node = kzalloc(sizeof(*node), allocflags); + if (!node) + return NULL; + + node->full_name = kstrdup(full_name, allocflags); + of_node_set_flag(node, OF_DYNAMIC); + of_node_set_flag(node, OF_DETACHED); + if (!node->full_name) + goto err_free; + + of_node_init(node); + + return node; + + err_free: + kfree(node->full_name); + kfree(node); + return NULL; +} diff --git a/drivers/of/of_private.h b/drivers/of/of_private.h index c270f2037779..1799ed2b3808 100644 --- a/drivers/of/of_private.h +++ b/drivers/of/of_private.h @@ -51,4 +51,14 @@ static inline int of_property_notify(int action, struct device_node *np, } #endif /* CONFIG_OF_DYNAMIC */ +/** + * General utilities for working with live trees. + * + * All functions with two leading underscores operate + * without taking node references, so you either have to + * own the devtree lock or work on detached trees only. + */ +struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags); +struct device_node *__of_node_alloc(const char *full_name, gfp_t allocflags); + #endif /* _LINUX_OF_PRIVATE_H */ diff --git a/drivers/of/selftest.c b/drivers/of/selftest.c index 077314eebb95..ee2166f0f36a 100644 --- a/drivers/of/selftest.c +++ b/drivers/of/selftest.c @@ -16,6 +16,8 @@ #include #include +#include "of_private.h" + static struct selftest_results { int passed; int failed; @@ -266,6 +268,31 @@ static void __init of_selftest_property_match_string(void) selftest(rc == -EILSEQ, "unterminated string; rc=%i", rc); } +#define propcmp(p1, p2) (((p1)->length == (p2)->length) && \ + (p1)->value && (p2)->value && \ + !memcmp((p1)->value, (p2)->value, (p1)->length) && \ + !strcmp((p1)->name, (p2)->name)) +static void __init of_selftest_property_copy(void) +{ +#ifdef CONFIG_OF_DYNAMIC + struct property p1 = { .name = "p1", .length = 0, .value = "" }; + struct property p2 = { .name = "p2", .length = 5, .value = "abcd" }; + struct property *new; + + new = __of_prop_dup(&p1, GFP_KERNEL); + selftest(new && propcmp(&p1, new), "empty property didn't copy correctly\n"); + kfree(new->value); + kfree(new->name); + kfree(new); + + new = __of_prop_dup(&p2, GFP_KERNEL); + selftest(new && propcmp(&p2, new), "non-empty property didn't copy correctly\n"); + kfree(new->value); + kfree(new->name); + kfree(new); +#endif +} + static void __init of_selftest_parse_interrupts(void) { struct device_node *np; @@ -533,6 +560,7 @@ static int __init of_selftest(void) of_selftest_dynamic(); of_selftest_parse_phandle_with_args(); of_selftest_property_match_string(); + of_selftest_property_copy(); of_selftest_parse_interrupts(); of_selftest_parse_interrupts_extended(); of_selftest_match_node();