From owner-svn-src-all@FreeBSD.ORG Thu Oct 31 02:11:36 2013 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTP id 2D4B82CE; Thu, 31 Oct 2013 02:11:36 +0000 (UTC) (envelope-from ian@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id 017E32546; Thu, 31 Oct 2013 02:11:36 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.7/8.14.7) with ESMTP id r9V2BZNW057450; Thu, 31 Oct 2013 02:11:35 GMT (envelope-from ian@svn.freebsd.org) Received: (from ian@localhost) by svn.freebsd.org (8.14.7/8.14.5/Submit) id r9V2BZc0057449; Thu, 31 Oct 2013 02:11:35 GMT (envelope-from ian@svn.freebsd.org) Message-Id: <201310310211.r9V2BZc0057449@svn.freebsd.org> From: Ian Lepore Date: Thu, 31 Oct 2013 02:11:35 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r257413 - head/sys/arm/freescale/imx X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 31 Oct 2013 02:11:36 -0000 Author: ian Date: Thu Oct 31 02:11:35 2013 New Revision: 257413 URL: http://svnweb.freebsd.org/changeset/base/257413 Log: Reset the timer interrupt status register at the top rather than bottom of the interrupt handler. If the event callback starts a new short timeout, the timer can fire before returning from the event callback, and clearing the interrupt status after that loses the interrupt and hangs until the counter wraps. Fixing all of this removes the need for the do-nothing loop at the top of the handler which really just waited for the counter to roll over and reach the one-shot count again. Also add a missing return(0) in the periodic timer start case. Modified: head/sys/arm/freescale/imx/imx_gpt.c Modified: head/sys/arm/freescale/imx/imx_gpt.c ============================================================================== --- head/sys/arm/freescale/imx/imx_gpt.c Thu Oct 31 02:04:53 2013 (r257412) +++ head/sys/arm/freescale/imx/imx_gpt.c Thu Oct 31 02:11:35 2013 (r257413) @@ -277,14 +277,9 @@ imx_gpt_timer_start(struct eventtimer *e WRITE4(sc, IMX_GPT_OCR2, READ4(sc, IMX_GPT_CNT) + sc->sc_period); /* Enable compare register 2 Interrupt */ SET4(sc, IMX_GPT_IR, GPT_IR_OF2); + return (0); } else if (first != 0) { ticks = ((uint32_t)et->et_frequency * first) >> 32; - - /* - * TODO: setupt second compare reg with time which will save - * us in case correct one lost, f.e. if period to short and - * setup done later than counter reach target value. - */ /* Do not disturb, otherwise event will be lost */ spinlock_enter(); /* Set expected value */ @@ -293,7 +288,6 @@ imx_gpt_timer_start(struct eventtimer *e SET4(sc, IMX_GPT_IR, GPT_IR_OF1); /* Now everybody can relax */ spinlock_exit(); - return (0); } @@ -341,27 +335,32 @@ imx_gpt_intr(void *arg) sc = (struct imx_gpt_softc *)arg; - /* Sometime we not get staus bit when interrupt arrive. Cache? */ - while (!(status = READ4(sc, IMX_GPT_SR))) - ; + status = READ4(sc, IMX_GPT_SR); + + /* + * Clear interrupt status before invoking event callbacks. The callback + * often sets up a new one-shot timer event and if the interval is short + * enough it can fire before we get out of this function. If we cleared + * at the bottom we'd miss the interrupt and hang until the clock wraps. + */ + WRITE4(sc, IMX_GPT_SR, status); + /* Handle one-shot timer events. */ if (status & GPT_IR_OF1) { if (sc->et.et_active) { sc->et.et_event_cb(&sc->et, sc->et.et_arg); } } + + /* Handle periodic timer events. */ if (status & GPT_IR_OF2) { - if (sc->et.et_active) { + if (sc->et.et_active) sc->et.et_event_cb(&sc->et, sc->et.et_arg); - /* Set expected value */ + if (sc->sc_period != 0) WRITE4(sc, IMX_GPT_OCR2, READ4(sc, IMX_GPT_CNT) + sc->sc_period); - } } - /* ACK */ - WRITE4(sc, IMX_GPT_SR, status); - return (FILTER_HANDLED); }