From patchwork Thu Mar 25 21:17:26 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Guzman Lugo, Fernando" X-Patchwork-Id: 88364 X-Patchwork-Delegate: omar.ramirez@ti.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o2PLHYja022358 for ; Thu, 25 Mar 2010 21:17:35 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752631Ab0CYVRe (ORCPT ); Thu, 25 Mar 2010 17:17:34 -0400 Received: from arroyo.ext.ti.com ([192.94.94.40]:50710 "EHLO arroyo.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752053Ab0CYVRd convert rfc822-to-8bit (ORCPT ); Thu, 25 Mar 2010 17:17:33 -0400 Received: from dlep34.itg.ti.com ([157.170.170.115]) by arroyo.ext.ti.com (8.13.7/8.13.7) with ESMTP id o2PLHTdg007235 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Thu, 25 Mar 2010 16:17:29 -0500 Received: from dlep26.itg.ti.com (localhost [127.0.0.1]) by dlep34.itg.ti.com (8.13.7/8.13.7) with ESMTP id o2PLHSdZ002704; Thu, 25 Mar 2010 16:17:28 -0500 (CDT) Received: from dlee74.ent.ti.com (localhost [127.0.0.1]) by dlep26.itg.ti.com (8.13.8/8.13.8) with ESMTP id o2PLHSrV007228; Thu, 25 Mar 2010 16:17:28 -0500 (CDT) Received: from dlee06.ent.ti.com ([157.170.170.11]) by dlee74.ent.ti.com ([157.170.170.8]) with mapi; Thu, 25 Mar 2010 16:17:28 -0500 From: "Guzman Lugo, Fernando" To: "linux-omap@vger.kernel.org" CC: "Doyu Hiroshi (Nokia-D/Helsinki)" , "Palande Ameya (Nokia-D/Helsinki)" , Felipe Contreras Date: Thu, 25 Mar 2010 16:17:26 -0500 Subject: [PATCH v2] DSPBRIDGE: DSP recovery feature Thread-Topic: [PATCH v2] DSPBRIDGE: DSP recovery feature Thread-Index: AcrMYJFr1p3cmVYdQomG2hf1Av9JXw== Message-ID: <496565EC904933469F292DDA3F1663E602CADC3396@dlee06.ent.ti.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: acceptlanguage: en-US MIME-Version: 1.0 Sender: linux-omap-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-omap@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Thu, 25 Mar 2010 21:17:35 +0000 (UTC) diff --git a/arch/arm/plat-omap/include/dspbridge/drv.h b/arch/arm/plat-omap/include/dspbridge/drv.h index 41deb86..947cbdd 100644 --- a/arch/arm/plat-omap/include/dspbridge/drv.h +++ b/arch/arm/plat-omap/include/dspbridge/drv.h @@ -386,4 +386,8 @@ extern dsp_status drv_request_resources(IN u32 dw_context, extern dsp_status drv_release_resources(IN u32 dw_context, struct drv_object *hdrv_obj); +#ifdef CONFIG_BRIDGE_RECOVERY +void bridge_recover_schedule(void); +#endif + #endif /* DRV_ */ diff --git a/drivers/dsp/bridge/Kconfig b/drivers/dsp/bridge/Kconfig index a3251c3..23b2afc 100644 --- a/drivers/dsp/bridge/Kconfig +++ b/drivers/dsp/bridge/Kconfig @@ -38,6 +38,13 @@ config BRIDGE_DEBUG help Say Y to enable Bridge debugging capabilities +config BRIDGE_RECOVERY + bool "DSP Recovery Support" + depends on MPU_BRIDGE + help + In case of DSP fatal error, BRIDGE driver will try to + recover itself. + comment "Bridge Notifications" depends on MPU_BRIDGE diff --git a/drivers/dsp/bridge/pmgr/wcd.c b/drivers/dsp/bridge/pmgr/wcd.c index f30e023..15a05a6 100644 --- a/drivers/dsp/bridge/pmgr/wcd.c +++ b/drivers/dsp/bridge/pmgr/wcd.c @@ -381,7 +381,7 @@ dsp_status wcd_init_complete2(void) dsp_status status = DSP_SOK; struct cfg_devnode *dev_node; struct dev_object *hdev_obj; - u32 dev_type; + u32 dev_type, tmp; DBC_REQUIRE(wcd_c_refs > 0); @@ -396,13 +396,11 @@ dsp_status wcd_init_complete2(void) if (DSP_FAILED(dev_get_dev_type(hdev_obj, &dev_type))) continue; - if ((dev_type == DSP_UNIT) || (dev_type == IVA_UNIT)) { - if (DSP_FAILED(proc_auto_start(dev_node, hdev_obj))) { - status = DSP_EFAIL; - /* break; */ - } - } - } /* End For Loop */ + if ((dev_type == DSP_UNIT) || (dev_type == IVA_UNIT)) + if (cfg_get_auto_start(dev_node, &tmp) == DSP_SOK + && tmp) + proc_auto_start(dev_node, hdev_obj); + } return status; } diff --git a/drivers/dsp/bridge/rmgr/drv_interface.c b/drivers/dsp/bridge/rmgr/drv_interface.c index d592181..5f01ab9 100644 --- a/drivers/dsp/bridge/rmgr/drv_interface.c +++ b/drivers/dsp/bridge/rmgr/drv_interface.c @@ -91,6 +91,15 @@ static s32 shm_size = 0x500000; /* 5 MB */ static u32 phys_mempool_base; static u32 phys_mempool_size; static int tc_wordswapon; /* Default value is always false */ +#ifdef CONFIG_BRIDGE_RECOVERY +#define REC_TIMEOUT 5000 /*recovery timeout in msecs */ +static atomic_t bridge_cref; /* number of bridge open handles */ +static struct workqueue_struct *bridge_rec_queue; +static struct work_struct bridge_recovery_work; +static DECLARE_COMPLETION_ONSTACK(bridge_comp); +static DECLARE_COMPLETION_ONSTACK(bridge_open_comp); +static bool recover; +#endif #ifdef CONFIG_PM struct omap34_xx_bridge_suspend_data { @@ -189,6 +198,33 @@ u32 vdd1_dsp_freq[6][4] = { {0, 430000, 355000, 430000}, }; +#ifdef CONFIG_BRIDGE_RECOVERY +static void bridge_recover(struct work_struct *work) +{ + struct dev_object *dev; + struct cfg_devnode *dev_node; + if (atomic_read(&bridge_cref)) { + INIT_COMPLETION(bridge_comp); + while (!wait_for_completion_timeout(&bridge_comp, + msecs_to_jiffies(REC_TIMEOUT))) + pr_info("%s:%d handle(s) still opened\n", + __func__, atomic_read(&bridge_cref)); + } + dev = dev_get_first(); + dev_get_dev_node(dev, &dev_node); + if (!dev_node || DSP_FAILED(proc_auto_start(dev_node, dev))) + pr_err("DSP could not be restarted\n"); + recover = false; + complete_all(&bridge_open_comp); +} + +void bridge_recover_schedule(void) +{ + INIT_COMPLETION(bridge_open_comp); + recover = true; + queue_work(bridge_rec_queue, &bridge_recovery_work); +} +#endif #ifdef CONFIG_BRIDGE_DVFS static int dspbridge_post_scale(struct notifier_block *op, unsigned long level, void *ptr) @@ -323,6 +359,11 @@ static int __devinit omap34_xx_bridge_probe(struct platform_device *pdev) } } +#ifdef CONFIG_BRIDGE_RECOVERY + bridge_rec_queue = create_workqueue("bridge_rec_queue"); + INIT_WORK(&bridge_recovery_work, bridge_recover); + INIT_COMPLETION(bridge_comp); +#endif DBC_ASSERT(status == 0); DBC_ASSERT(DSP_SUCCEEDED(init_status)); @@ -443,6 +484,14 @@ static int bridge_open(struct inode *ip, struct file *filp) * Allocate a new process context and insert it into global * process context list. */ + +#ifdef CONFIG_BRIDGE_RECOVERY + if (recover) { + if (filp->f_flags & O_NONBLOCK || + wait_for_completion_interruptible(&bridge_open_comp)) + return -EBUSY; + } +#endif pr_ctxt = mem_calloc(sizeof(struct process_context), MEM_PAGED); if (pr_ctxt) { pr_ctxt->res_state = PROC_RES_ALLOCATED; @@ -457,7 +506,10 @@ static int bridge_open(struct inode *ip, struct file *filp) } filp->private_data = pr_ctxt; - +#ifdef CONFIG_BRIDGE_RECOVERY + if (!status) + atomic_inc(&bridge_cref); +#endif return status; } @@ -484,6 +536,10 @@ static int bridge_release(struct inode *ip, struct file *filp) filp->private_data = NULL; err: +#ifdef CONFIG_BRIDGE_RECOVERY + if (!atomic_dec_return(&bridge_cref)) + complete(&bridge_comp); +#endif return status; } @@ -496,6 +552,12 @@ static long bridge_ioctl(struct file *filp, unsigned int code, union Trapped_Args buf_in; DBC_REQUIRE(filp != NULL); +#ifdef CONFIG_BRIDGE_RECOVERY + if (recover) { + status = -EIO; + goto err; + } +#endif #ifdef CONFIG_PM status = omap34_xxbridge_suspend_lockout(&bridge_suspend_data, filp); if (status != 0) diff --git a/drivers/dsp/bridge/rmgr/proc.c b/drivers/dsp/bridge/rmgr/proc.c index b3e4546..1556285 100644 --- a/drivers/dsp/bridge/rmgr/proc.c +++ b/drivers/dsp/bridge/rmgr/proc.c @@ -53,6 +53,7 @@ #include #include #include +#include /* ----------------------------------- This */ #include @@ -268,7 +269,6 @@ dsp_status proc_auto_start(struct cfg_devnode *dev_node_obj, struct dev_object *hdev_obj) { dsp_status status = DSP_EFAIL; - u32 dw_auto_start = 0; /* autostart flag */ struct proc_object *p_proc_object; char sz_exec_file[MAXCMDLINELEN]; char *argv[2]; @@ -304,11 +304,6 @@ dsp_status proc_auto_start(struct cfg_devnode *dev_node_obj, if (DSP_FAILED(status)) goto func_cont; - status = cfg_get_auto_start(dev_node_obj, &dw_auto_start); - if (DSP_FAILED(status) || !dw_auto_start) { - status = DSP_EFAIL; - goto func_cont; - } /* Get the default executable for this board... */ dev_get_dev_type(hdev_obj, (u32 *) &dev_type); p_proc_object->processor_id = dev_type; @@ -1031,6 +1026,8 @@ dsp_status proc_load(void *hprocessor, IN CONST s32 argc_index, if (DSP_SUCCEEDED((*p_proc_object->intf_fxns->pfn_brd_status) (p_proc_object->hwmd_context, &brd_state))) { pr_info("%s: Processor Loaded %s\n", __func__, pargv0); + reg_set_value(DEFEXEC, (u8 *)pargv0, + strlen(pargv0) + 1); DBC_ASSERT(brd_state == BRD_LOADED); } } diff --git a/drivers/dsp/bridge/wmd/ue_deh.c b/drivers/dsp/bridge/wmd/ue_deh.c index 231b05e..14dd8ae 100644 --- a/drivers/dsp/bridge/wmd/ue_deh.c +++ b/drivers/dsp/bridge/wmd/ue_deh.c @@ -288,8 +288,12 @@ void bridge_deh_notify(struct deh_mgr *hdeh_mgr, u32 ulEventMask, u32 dwErrInfo) } /* Filter subsequent notifications when an error occurs */ - if (dev_context->dw_brd_state != BRD_ERROR) + if (dev_context->dw_brd_state != BRD_ERROR) { ntfy_notify(deh_mgr_obj->ntfy_obj, ulEventMask); +#ifdef CONFIG_BRIDGE_RECOVERY + bridge_recover_schedule(); +#endif + } /* Set the Board state as ERROR */ dev_context->dw_brd_state = BRD_ERROR;