From patchwork Wed Aug 8 23:07:44 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Guzman Lugo, Fernando" X-Patchwork-Id: 1298191 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork2.kernel.org (Postfix) with ESMTP id 57A0DDF223 for ; Wed, 8 Aug 2012 23:11:08 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1SzFMh-0007hl-Rz; Wed, 08 Aug 2012 23:08:35 +0000 Received: from na3sys009aog135.obsmtp.com ([74.125.149.84]) by merlin.infradead.org with smtps (Exim 4.76 #1 (Red Hat Linux)) id 1SzFMG-0007aP-2N for linux-arm-kernel@lists.infradead.org; Wed, 08 Aug 2012 23:08:12 +0000 Received: from mail-ob0-f182.google.com ([209.85.214.182]) (using TLSv1) by na3sys009aob135.postini.com ([74.125.148.12]) with SMTP ID DSNKUCLxVHCMjIpQbncXBDwiYrG5XxfzoizS@postini.com; Wed, 08 Aug 2012 16:08:07 PDT Received: by obbun3 with SMTP id un3so2391894obb.13 for ; Wed, 08 Aug 2012 16:08:04 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references :x-gm-message-state; bh=P0FyyLAZQpGqBJ9PMJOEiTNPcde3Ob9jl6LvtHzQ08c=; b=XZJGks+BLpQQ286PejLhH6mkCpiDNkRMG0LsaIXI1PWsUkiq9oWeel8pmQ5vas992x EK4uSQpkfbOyUVnpoYxlUwMJUfZ/0oadSVJO0EexuGuE2m66EYMixZmoUMkAP9hwC710 vWPwTxwagSM6CCZw3WyppuBirYsb1f/DQxaxbrUNtjfegeWO0bjRX/B8tlYzRobwqKbd CAemCfhuVMIAAytoMdhC2Dtbs5gYvN7BRjv6/QFDFOc2pKD2oAPeyj2wTMi7q1YOwO4b N1M/TO14cQ3zbqCCsSN4LA4UpKmf2m47qrMvuzjOHRErrmu8YbH2p515QEytwfOH2yJc zODw== Received: by 10.182.50.103 with SMTP id b7mr32625441obo.15.1344467284407; Wed, 08 Aug 2012 16:08:04 -0700 (PDT) Received: from localhost.localdomain (dragon.ti.com. [192.94.94.33]) by mx.google.com with ESMTPS id pj4sm23571216obb.20.2012.08.08.16.08.03 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 08 Aug 2012 16:08:03 -0700 (PDT) From: Fernando Guzman Lugo To: , , , Subject: [PATCH 3/3] remoteproc: create debugfs entry to disable/enable recovery dynamically Date: Wed, 8 Aug 2012 18:07:44 -0500 Message-Id: <1344467264-5128-4-git-send-email-fernando.lugo@ti.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1344467264-5128-1-git-send-email-fernando.lugo@ti.com> References: <1344467264-5128-1-git-send-email-fernando.lugo@ti.com> X-Gm-Message-State: ALoCoQkIMv89C3Yir4//yD0MqbAioqEQfHjHwoJYLXyIlJky1YNFy0DgTnTbv/vZufAoj2EZAIKh X-Spam-Note: CRM114 invocation failed X-Spam-Score: -4.2 (----) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-4.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -2.3 RCVD_IN_DNSWL_MED RBL: Sender listed at http://www.dnswl.org/, medium trust [74.125.149.84 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: Fernando Guzman Lugo X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Add a debugfs entry (named recovery) so that recovery can be disabled dynamically at runtime. This entry is very useful when you are trying to debug a rproc crash. Without this a recovery will take place making impossible to debug the issue. Original idea from Ohad Ben-Cohen and contributions from Subramaniam Chanderashekarapuram Example: -disabling recovery: $ echo disabled > /remoteproc/remoteproc0/recovery -enabling recovery: $ echo enabled > /remoteproc/remoteproc0/recovery -in case you have disabled recovery and you want to continue debugging you can recover the remoteproc once using recover. This will not change the state of the recovery entry, it will only recovery the rproc if its state is RPROC_CRASHED $ echo recover > /remoteproc/remoteproc0/recovery Signed-off-by: Fernando Guzman Lugo --- drivers/remoteproc/remoteproc_core.c | 3 +- drivers/remoteproc/remoteproc_debugfs.c | 83 +++++++++++++++++++++++++++++++ include/linux/remoteproc.h | 2 + 3 files changed, 87 insertions(+), 1 deletions(-) diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index c879069..0b52169 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -932,7 +932,8 @@ static void rproc_crash_handler_work(struct work_struct *work) ++rproc->crash_cnt, rproc->name); mutex_unlock(&rproc->lock); - rproc_trigger_recover(rproc); + if (!rproc->recovery_disabled) + rproc_trigger_recover(rproc); } /** diff --git a/drivers/remoteproc/remoteproc_debugfs.c b/drivers/remoteproc/remoteproc_debugfs.c index 0383385..aa95cde 100644 --- a/drivers/remoteproc/remoteproc_debugfs.c +++ b/drivers/remoteproc/remoteproc_debugfs.c @@ -28,6 +28,9 @@ #include #include #include +#include + +#include "remoteproc_internal.h" /* remoteproc debugfs parent dir */ static struct dentry *rproc_dbg; @@ -111,6 +114,84 @@ static const struct file_operations rproc_name_ops = { .llseek = generic_file_llseek, }; +/* expose recovery flag via debugfs */ +static ssize_t rproc_recovery_read(struct file *filp, char __user *userbuf, + size_t count, loff_t *ppos) +{ + struct rproc *rproc = filp->private_data; + char *buf = rproc->recovery_disabled ? "disabled\n" : "enabled\n"; + + return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf)); +} + + +/* + * Writing to the recovey debugfs entry we can change the behavior of the + * recovery dynamically. The default value of this entry is "enabled". + * + * There are 3 possible options you can write to the recovery debug entry: + * "enabled", "disabled" and "recover" + * + * enabled: In this case recovery will be enabled, every time there is a + * rproc crashed the rproc will be recovered. If recovery has been + * disabled and it crashed and you enable recovery it will be + * recover as soon as you enable recovery. + * disabled: In this case recovery will be disabled, that means if a rproc + * crashes it will remain in crashed state. Therefore the rproc + * won't be functional any more. But this option is used for + * debugging purposes. Otherwise, debugging a crash would not be + * possible. + * recover: This function will trigger a recovery without taking care of + * the recovery state (enabled/disabled) and without changing it. + * This useful for the cases when you are debugging a crash and + * after enabling recovery you get another crash immediately. As + * the recovery state will be enabled it will recover the rproc + * without let you debug the new crash. So, it is recommended to + * disabled recovery, then starting debugging and use "recovery" + * command while still debugging and when you are done then you + * case use enabled command. + */ +static ssize_t rproc_recovery_write(struct file *filp, + const char __user *user_buf, size_t count, loff_t *ppos) +{ + struct rproc *rproc = filp->private_data; + char buf[10]; + int ret; + + if (count > sizeof(buf)) + return count; + + ret = copy_from_user(buf, user_buf, count); + if (ret) + return ret; + + /* remove end of line */ + if (buf[count - 1] == '\n') + buf[count - 1] = '\0'; + + if (!strncmp(buf, "enabled", count)) { + rproc->recovery_disabled = false; + /* if rproc has crashed trigger recovery */ + if (rproc->state == RPROC_CRASHED) + rproc_trigger_recover(rproc); + } else if (!strncmp(buf, "disabled", count)) { + rproc->recovery_disabled = true; + } else if (!strncmp(buf, "recover", count)) { + /* if rproc has crashed trigger recovery */ + if (rproc->state == RPROC_CRASHED) + rproc_trigger_recover(rproc); + } + + return count; +} + +static const struct file_operations rproc_recovery_ops = { + .read = rproc_recovery_read, + .write = rproc_recovery_write, + .open = simple_open, + .llseek = generic_file_llseek, +}; + void rproc_remove_trace_file(struct dentry *tfile) { debugfs_remove(tfile); @@ -154,6 +235,8 @@ void rproc_create_debug_dir(struct rproc *rproc) rproc, &rproc_name_ops); debugfs_create_file("state", 0400, rproc->dbg_dir, rproc, &rproc_state_ops); + debugfs_create_file("recovery", 0400, rproc->dbg_dir, + rproc, &rproc_recovery_ops); } void __init rproc_init_debugfs(void) diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h index a46ed27..1f73c75 100644 --- a/include/linux/remoteproc.h +++ b/include/linux/remoteproc.h @@ -398,6 +398,7 @@ enum rproc_crash_type { * @index: index of this rproc device * @crash_handler: workqueue for handling a crash * @crash_cnt: crash counter + * @recovery_disabled: flag that state if recovery was disabled */ struct rproc { struct klist_node node; @@ -423,6 +424,7 @@ struct rproc { int index; struct work_struct crash_handler; unsigned crash_cnt; + bool recovery_disabled; }; /* we currently support only two vrings per rvdev */