From patchwork Wed Jul 23 23:44:19 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Grant Likely X-Patchwork-Id: 34180 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-vc0-f197.google.com (mail-vc0-f197.google.com [209.85.220.197]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 1EF7B20672 for ; Wed, 23 Jul 2014 23:44:53 +0000 (UTC) Received: by mail-vc0-f197.google.com with SMTP id ij19sf5939549vcb.8 for ; Wed, 23 Jul 2014 16:44:52 -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=kta3wkChUQrHsdfKrTwCyQwIn3q4fOYkxXT+T76WmmE=; b=OZCvpTB4xpW2qC8Zc+WXL2O3Pp+kvRlkaHGTWJp5zETCyF1E3n6Gnj/WCLhjqy/A7F +IPROjk+rGnS0G3zMvxZ8ZjwkaoFczdyzYEk7mHTonSoTgM5SzjGpuXQwgo2W6vkUAyR KKUHNLPIKJlX7B4gmc297xMEFRgUcN0zEpoEz5I2p0DsCk7rOvtnveuTJZwy/OgewYCY khqoCRtPHS/n4wnxy0nLx2Ji9rpbYC2Fq+jCXBflrlkPyMCltIAi4sJghBPp6Hu2Ksbt N31sJbf8j9JeAxTxdjWWX/NmF8mbCKbyP6G8XzzAU8is8UTyOi0hcbUGgtjIVA4SoYLZ yeKA== X-Gm-Message-State: ALoCoQk9zbbu3tfdgfg0EgoP1fVgxDDxH4GkCaPljXrEwTtF4FHsXW4b9KtZNuHtUfcwx9CTH5QK X-Received: by 10.52.190.129 with SMTP id gq1mr2081764vdc.2.1406159092877; Wed, 23 Jul 2014 16:44:52 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.19.144 with SMTP id 16ls539940qgh.27.gmail; Wed, 23 Jul 2014 16:44:52 -0700 (PDT) X-Received: by 10.221.47.9 with SMTP id uq9mr7155994vcb.48.1406159092758; Wed, 23 Jul 2014 16:44:52 -0700 (PDT) Received: from mail-vc0-f178.google.com (mail-vc0-f178.google.com [209.85.220.178]) by mx.google.com with ESMTPS id s7si3810577vcl.50.2014.07.23.16.44.52 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 23 Jul 2014 16:44:52 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.178 as permitted sender) client-ip=209.85.220.178; Received: by mail-vc0-f178.google.com with SMTP id la4so3609701vcb.37 for ; Wed, 23 Jul 2014 16:44:52 -0700 (PDT) X-Received: by 10.220.118.136 with SMTP id v8mr7079286vcq.50.1406159092648; Wed, 23 Jul 2014 16:44:52 -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 tc5csp320940vcb; Wed, 23 Jul 2014 16:44:52 -0700 (PDT) X-Received: by 10.66.161.38 with SMTP id xp6mr6049647pab.15.1406159091790; Wed, 23 Jul 2014 16:44:51 -0700 (PDT) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id fl5si4020418pbb.220.2014.07.23.16.44.51 for ; Wed, 23 Jul 2014 16:44:51 -0700 (PDT) Received-SPF: none (google.com: linux-kernel-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 S932892AbaGWXom (ORCPT + 16 others); Wed, 23 Jul 2014 19:44:42 -0400 Received: from mail-pa0-f46.google.com ([209.85.220.46]:49187 "EHLO mail-pa0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1758541AbaGWXok (ORCPT ); Wed, 23 Jul 2014 19:44:40 -0400 Received: by mail-pa0-f46.google.com with SMTP id lj1so2674053pab.33 for ; Wed, 23 Jul 2014 16:44:39 -0700 (PDT) X-Received: by 10.70.44.2 with SMTP id a2mr6181559pdm.38.1406159079866; Wed, 23 Jul 2014 16:44:39 -0700 (PDT) Received: from trevor.secretlab.ca (S0106602ad082623c.cg.shawcable.net. [68.146.69.61]) by mx.google.com with ESMTPSA id fq4sm4770209pdb.71.2014.07.23.16.44.37 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 23 Jul 2014 16:44:39 -0700 (PDT) Received: by trevor.secretlab.ca (Postfix, from userid 1000) id D3A8AC439FA; 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 05/10] of: Create unlocked versions of node and property add/remove functions Date: Wed, 23 Jul 2014 17:44:19 -0600 Message-Id: <1406159064-21366-6-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: linux-kernel-owner@vger.kernel.org Precedence: list List-ID: X-Mailing-List: linux-kernel@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.178 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 The DT overlay code will need to manipulate nodes and properties while already holding the devicetree lock, or on nodes that are not yet attached to the tree, but the current helper functions don't allow that. Extract the core behaviour from the accessors and create the following unlocked variants. The unlocked variants require either the lock to already be held or for the nodes to be detached from the tree. Changes to live nodes will not get updated in sysfs, so the caller must arrange for housekeeping to take place after dropping the lock. The new functions are: __of_add_property(), __of_remove_property(), __of_update_property(), __of_attach_node() and __of_detach_node(). Signed-off-by: Pantelis Antoniou [Remove unnecessary diff hunks and rewrite commit text] Signed-off-by: Grant Likely --- drivers/of/base.c | 91 +++++++++++++++++++++++++++++-------------------- drivers/of/dynamic.c | 63 ++++++++++++++++++---------------- drivers/of/of_private.h | 8 +++++ 3 files changed, 96 insertions(+), 66 deletions(-) diff --git a/drivers/of/base.c b/drivers/of/base.c index 0d8955605738..b403f9d98461 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1659,7 +1659,7 @@ EXPORT_SYMBOL(of_count_phandle_with_args); /** * __of_add_property - Add a property to a node without lock operations */ -static int __of_add_property(struct device_node *np, struct property *prop) +int __of_add_property(struct device_node *np, struct property *prop) { struct property **next; @@ -1701,6 +1701,25 @@ int of_add_property(struct device_node *np, struct property *prop) return rc; } +int __of_remove_property(struct device_node *np, struct property *prop) +{ + struct property **next; + + for (next = &np->properties; *next; next = &(*next)->next) { + if (*next == prop) + break; + } + if (*next == NULL) + return -ENODEV; + + /* found the node */ + *next = prop->next; + prop->next = np->deadprops; + np->deadprops = prop; + + return 0; +} + /** * of_remove_property - Remove a property from a node. * @@ -1711,9 +1730,7 @@ int of_add_property(struct device_node *np, struct property *prop) */ int of_remove_property(struct device_node *np, struct property *prop) { - struct property **next; unsigned long flags; - int found = 0; int rc; rc = of_property_notify(OF_RECONFIG_REMOVE_PROPERTY, np, prop); @@ -1721,22 +1738,11 @@ int of_remove_property(struct device_node *np, struct property *prop) return rc; raw_spin_lock_irqsave(&devtree_lock, flags); - next = &np->properties; - while (*next) { - if (*next == prop) { - /* found the node */ - *next = prop->next; - prop->next = np->deadprops; - np->deadprops = prop; - found = 1; - break; - } - next = &(*next)->next; - } + rc = __of_remove_property(np, prop); raw_spin_unlock_irqrestore(&devtree_lock, flags); - if (!found) - return -ENODEV; + if (rc) + return rc; /* at early boot, bail hear and defer setup to of_init() */ if (!of_kset) @@ -1747,6 +1753,32 @@ int of_remove_property(struct device_node *np, struct property *prop) return 0; } +int __of_update_property(struct device_node *np, struct property *newprop, + struct property **oldpropp) +{ + struct property **next, *oldprop; + + for (next = &np->properties; *next; next = &(*next)->next) { + if (of_prop_cmp((*next)->name, newprop->name) == 0) + break; + } + *oldpropp = oldprop = *next; + + if (oldprop) { + /* replace the node */ + newprop->next = oldprop->next; + *next = newprop; + oldprop->next = np->deadprops; + np->deadprops = oldprop; + } else { + /* new node */ + newprop->next = NULL; + *next = newprop; + } + + return 0; +} + /* * of_update_property - Update a property in a node, if the property does * not exist, add it. @@ -1758,34 +1790,19 @@ int of_remove_property(struct device_node *np, struct property *prop) */ int of_update_property(struct device_node *np, struct property *newprop) { - struct property **next, *oldprop; + struct property *oldprop; unsigned long flags; int rc; + if (!newprop->name) + return -EINVAL; + rc = of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop); if (rc) return rc; - if (!newprop->name) - return -EINVAL; - raw_spin_lock_irqsave(&devtree_lock, flags); - next = &np->properties; - oldprop = __of_find_property(np, newprop->name, NULL); - if (!oldprop) { - /* add the new node */ - rc = __of_add_property(np, newprop); - } else while (*next) { - /* replace the node */ - if (*next == oldprop) { - newprop->next = oldprop->next; - *next = newprop; - oldprop->next = np->deadprops; - np->deadprops = oldprop; - break; - } - next = &(*next)->next; - } + rc = __of_update_property(np, newprop, &oldprop); raw_spin_unlock_irqrestore(&devtree_lock, flags); if (rc) return rc; diff --git a/drivers/of/dynamic.c b/drivers/of/dynamic.c index e0c4c6e25980..75fcc66fcefd 100644 --- a/drivers/of/dynamic.c +++ b/drivers/of/dynamic.c @@ -94,6 +94,15 @@ int of_property_notify(int action, struct device_node *np, return of_reconfig_notify(action, &pr); } +void __of_attach_node(struct device_node *np) +{ + np->sibling = np->parent->child; + np->allnext = np->parent->allnext; + np->parent->allnext = np; + np->parent->child = np; + of_node_clear_flag(np, OF_DETACHED); +} + /** * of_attach_node() - Plug a device node into the tree and global list. */ @@ -107,46 +116,23 @@ int of_attach_node(struct device_node *np) return rc; raw_spin_lock_irqsave(&devtree_lock, flags); - np->sibling = np->parent->child; - np->allnext = np->parent->allnext; - np->parent->allnext = np; - np->parent->child = np; - of_node_clear_flag(np, OF_DETACHED); + __of_attach_node(np); raw_spin_unlock_irqrestore(&devtree_lock, flags); of_node_add(np); return 0; } -/** - * of_detach_node() - "Unplug" a node from the device tree. - * - * The caller must hold a reference to the node. The memory associated with - * the node is not freed until its refcount goes to zero. - */ -int of_detach_node(struct device_node *np) +void __of_detach_node(struct device_node *np) { struct device_node *parent; - unsigned long flags; - int rc = 0; - - rc = of_reconfig_notify(OF_RECONFIG_DETACH_NODE, np); - if (rc) - return rc; - raw_spin_lock_irqsave(&devtree_lock, flags); - - if (of_node_check_flag(np, OF_DETACHED)) { - /* someone already detached it */ - raw_spin_unlock_irqrestore(&devtree_lock, flags); - return rc; - } + if (WARN_ON(of_node_check_flag(np, OF_DETACHED))) + return; parent = np->parent; - if (!parent) { - raw_spin_unlock_irqrestore(&devtree_lock, flags); - return rc; - } + if (WARN_ON(!parent)) + return; if (of_allnodes == np) of_allnodes = np->allnext; @@ -171,6 +157,25 @@ int of_detach_node(struct device_node *np) } of_node_set_flag(np, OF_DETACHED); +} + +/** + * of_detach_node() - "Unplug" a node from the device tree. + * + * The caller must hold a reference to the node. The memory associated with + * the node is not freed until its refcount goes to zero. + */ +int of_detach_node(struct device_node *np) +{ + unsigned long flags; + int rc = 0; + + rc = of_reconfig_notify(OF_RECONFIG_DETACH_NODE, np); + if (rc) + return rc; + + raw_spin_lock_irqsave(&devtree_lock, flags); + __of_detach_node(np); raw_spin_unlock_irqrestore(&devtree_lock, flags); of_node_remove(np); diff --git a/drivers/of/of_private.h b/drivers/of/of_private.h index 1799ed2b3808..0f6089722af9 100644 --- a/drivers/of/of_private.h +++ b/drivers/of/of_private.h @@ -61,4 +61,12 @@ static inline int of_property_notify(int action, struct device_node *np, 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); +extern int __of_add_property(struct device_node *np, struct property *prop); +extern int __of_remove_property(struct device_node *np, struct property *prop); +extern int __of_update_property(struct device_node *np, + struct property *newprop, struct property **oldprop); + +extern void __of_attach_node(struct device_node *np); +extern void __of_detach_node(struct device_node *np); + #endif /* _LINUX_OF_PRIVATE_H */