From patchwork Fri Sep 12 20:56:48 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Suman Anna X-Patchwork-Id: 4898181 Return-Path: X-Original-To: patchwork-linux-omap@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 7F18CBEEA5 for ; Fri, 12 Sep 2014 20:58:21 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 4034E2026F for ; Fri, 12 Sep 2014 20:58:19 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 481FB20225 for ; Fri, 12 Sep 2014 20:58:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752744AbaILU57 (ORCPT ); Fri, 12 Sep 2014 16:57:59 -0400 Received: from arroyo.ext.ti.com ([192.94.94.40]:35556 "EHLO arroyo.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752411AbaILU5Q (ORCPT ); Fri, 12 Sep 2014 16:57:16 -0400 Received: from dflxv15.itg.ti.com ([128.247.5.124]) by arroyo.ext.ti.com (8.13.7/8.13.7) with ESMTP id s8CKuoM1014148; Fri, 12 Sep 2014 15:56:50 -0500 Received: from DLEE71.ent.ti.com (dlee71.ent.ti.com [157.170.170.114]) by dflxv15.itg.ti.com (8.14.3/8.13.8) with ESMTP id s8CKuogD020494; Fri, 12 Sep 2014 15:56:50 -0500 Received: from dlep33.itg.ti.com (157.170.170.75) by DLEE71.ent.ti.com (157.170.170.114) with Microsoft SMTP Server id 14.3.174.1; Fri, 12 Sep 2014 15:56:51 -0500 Received: from legion.dal.design.ti.com (legion.dal.design.ti.com [128.247.22.53]) by dlep33.itg.ti.com (8.14.3/8.13.8) with ESMTP id s8CKun3O003976; Fri, 12 Sep 2014 15:56:49 -0500 Received: from localhost (irmo.am.dhcp.ti.com [128.247.71.175]) by legion.dal.design.ti.com (8.11.7p1+Sun/8.11.7) with ESMTP id s8CKunt07007; Fri, 12 Sep 2014 15:56:49 -0500 (CDT) From: Suman Anna To: Ohad Ben-Cohen , Kumar Gala CC: Josh Cartwright , Bjorn Andersson , , , , , Suman Anna Subject: [RFC PATCHv2 3/3] hwspinlock/core: add support for reserved locks Date: Fri, 12 Sep 2014 15:56:48 -0500 Message-ID: <1410555408-56954-4-git-send-email-s-anna@ti.com> X-Mailer: git-send-email 2.0.4 In-Reply-To: <1410555408-56954-1-git-send-email-s-anna@ti.com> References: <1410555408-56954-1-git-send-email-s-anna@ti.com> MIME-Version: 1.0 Sender: linux-omap-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-omap@vger.kernel.org X-Spam-Status: No, score=-9.1 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The HwSpinlock core allows requesting either a specific lock or an available normal lock. The specific locks are usually reserved during board init time, while the normal available locks are intended to be assigned at runtime for clients that do not care about a specific lock. The HwSpinlock core has been enhanced to: 1. mark certain locks as 'reserved' by parsing the DT blob for any locks used by client nodes. 2. restrict the anonymous hwspin_lock_request() API to allocate only from non-reserved locks for DT boots. 3. limit these reserved locks to be allocated only using the hwspin_lock_request_specific() API for DT boots. Signed-off-by: Suman Anna --- drivers/hwspinlock/hwspinlock_core.c | 61 ++++++++++++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 2 deletions(-) diff --git a/drivers/hwspinlock/hwspinlock_core.c b/drivers/hwspinlock/hwspinlock_core.c index f0d8475..d49a077 100644 --- a/drivers/hwspinlock/hwspinlock_core.c +++ b/drivers/hwspinlock/hwspinlock_core.c @@ -474,6 +474,53 @@ static int hwspinlock_device_add(struct hwspinlock_device *bank) } /** + * hwspin_mark_reserved_locks() - mark reserved locks + * + * This is an internal function that mark all the reserved locks within + * a hwspinlock device during the registration phase, and is applicable + * only for device-tree boots. The locks are marked by browsing through + * all the user nodes with the property "hwlocks", so that a separate + * property is not needed in the hwspinlock device itself. Note that it + * also marks locks used on disabled user nodes. + */ +static void hwspin_mark_reserved_locks(struct hwspinlock_device *bank) +{ + struct device_node *np = bank->dev->of_node; + const char *prop_name = "hwlocks"; + const char *cells_name = "#hwlock-cells"; + struct device_node *node = NULL; + struct of_phandle_args args; + struct hwspinlock *hwlock; + int i, id, count, ret; + + for_each_node_with_property(node, prop_name) { + count = of_count_phandle_with_args(node, prop_name, cells_name); + if (count <= 0) + continue; + + for (i = 0; i < count; i++, of_node_put(args.np)) { + args.np = NULL; + ret = of_parse_phandle_with_args(node, prop_name, + cells_name, i, &args); + if (ret || np != args.np) + continue; + + id = of_hwspin_lock_simple_xlate(bank, &args); + if (id < 0 || id >= bank->num_locks) + continue; + + hwlock = &bank->lock[id]; + if (hwlock->type == HWSPINLOCK_RESERVED) { + dev_err(bank->dev, "potential reuse of hwspinlock %d between multiple clients on %s\n", + id, np->full_name); + continue; + } + hwlock->type = HWSPINLOCK_RESERVED; + } + } +} + +/** * hwspin_lock_register() - register a new hw spinlock device * @bank: the hwspinlock device, which usually provides numerous hw locks * @dev: the backing device @@ -511,12 +558,16 @@ int hwspin_lock_register(struct hwspinlock_device *bank, struct device *dev, if (ret) return ret; + if (dev->of_node) + hwspin_mark_reserved_locks(bank); + for (i = 0; i < num_locks; i++) { hwlock = &bank->lock[i]; spin_lock_init(&hwlock->lock); hwlock->bank = bank; - hwlock->type = HWSPINLOCK_UNUSED; + if (hwlock->type != HWSPINLOCK_RESERVED) + hwlock->type = HWSPINLOCK_UNUSED; ret = hwspin_lock_register_single(hwlock, base_id + i); if (ret) @@ -699,7 +750,13 @@ struct hwspinlock *hwspin_lock_request_specific(unsigned int id) /* sanity check (this shouldn't happen) */ WARN_ON(hwlock_to_id(hwlock) != id); - /* make sure this hwspinlock is unused */ + if (hwlock->bank->dev->of_node && hwlock->type != HWSPINLOCK_RESERVED) { + pr_warn("hwspinlock %u is not a reserved lock\n", id); + hwlock = NULL; + goto out; + } + + /* make sure this hwspinlock is an unused reserved lock */ ret = radix_tree_tag_get(&hwspinlock_tree, id, hwlock->type); if (ret == 0) { pr_warn("hwspinlock %u is already in use\n", id);