From owner-svn-src-head@FreeBSD.ORG Wed Jan 1 20:35:39 2014 Return-Path: Delivered-To: svn-src-head@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 ESMTPS id 8127734A; Wed, 1 Jan 2014 20:35:39 +0000 (UTC) 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 5397A131B; Wed, 1 Jan 2014 20:35:39 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.7/8.14.7) with ESMTP id s01KZdXk021605; Wed, 1 Jan 2014 20:35:39 GMT (envelope-from zbb@svn.freebsd.org) Received: (from zbb@localhost) by svn.freebsd.org (8.14.7/8.14.7/Submit) id s01KZdc0021604; Wed, 1 Jan 2014 20:35:39 GMT (envelope-from zbb@svn.freebsd.org) Message-Id: <201401012035.s01KZdc0021604@svn.freebsd.org> From: Zbigniew Bodek Date: Wed, 1 Jan 2014 20:35:39 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r260166 - head/sys/arm/versatile X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.17 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 01 Jan 2014 20:35:39 -0000 Author: zbb Date: Wed Jan 1 20:35:38 2014 New Revision: 260166 URL: http://svnweb.freebsd.org/changeset/base/260166 Log: Fix race condition in DELAY for SP804 timer. Fix race condition in DELAY function: sc->tc was not initialized yet when time_counter pointer was set, what resulted in NULL pointer dereference. Export sysfreq to dts. Submitted by: Wojciech Macek Obtained from: Semihalf Modified: head/sys/arm/versatile/sp804.c Modified: head/sys/arm/versatile/sp804.c ============================================================================== --- head/sys/arm/versatile/sp804.c Wed Jan 1 20:26:08 2014 (r260165) +++ head/sys/arm/versatile/sp804.c Wed Jan 1 20:35:38 2014 (r260166) @@ -100,6 +100,7 @@ struct sp804_timer_softc { struct timecounter tc; bool et_enabled; struct eventtimer et; + int timer_initialized; }; /* Read/Write macros for Timer used as timecounter */ @@ -198,6 +199,8 @@ sp804_timer_attach(device_t dev) int rid = 0; int i; uint32_t id, reg; + phandle_t node; + pcell_t clock; sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (sc->mem_res == NULL) { @@ -215,8 +218,12 @@ sp804_timer_attach(device_t dev) return (ENXIO); } - /* TODO: get frequency from FDT */ sc->sysclk_freq = DEFAULT_FREQUENCY; + /* Get the base clock frequency */ + node = ofw_bus_get_node(dev); + if ((OF_getprop(node, "clock-frequency", &clock, sizeof(clock))) > 0) { + sc->sysclk_freq = fdt32_to_cpu(clock); + } /* Setup and enable the timer */ if (bus_setup_intr(dev, sc->irq_res, INTR_TYPE_CLK, @@ -234,8 +241,8 @@ sp804_timer_attach(device_t dev) /* * Timer 1, timecounter */ - sc->tc.tc_frequency = DEFAULT_FREQUENCY; - sc->tc.tc_name = "SP804 Timecouter"; + sc->tc.tc_frequency = sc->sysclk_freq; + sc->tc.tc_name = "SP804 Time Counter"; sc->tc.tc_get_timecount = sp804_timer_tc_get_timecount; sc->tc.tc_poll_pps = NULL; sc->tc.tc_counter_mask = ~0u; @@ -283,6 +290,8 @@ sp804_timer_attach(device_t dev) device_printf(dev, "PrimeCell ID: %08x\n", id); + sc->timer_initialized = 1; + return (0); } @@ -309,10 +318,18 @@ DELAY(int usec) uint32_t first, last; device_t timer_dev; struct sp804_timer_softc *sc; + int timer_initialized = 0; timer_dev = devclass_get_device(sp804_timer_devclass, 0); - if (timer_dev == NULL) { + if (timer_dev) { + sc = device_get_softc(timer_dev); + + if (sc) + timer_initialized = sc->timer_initialized; + } + + if (!timer_initialized) { /* * Timer is not initialized yet */ @@ -323,8 +340,6 @@ DELAY(int usec) return; } - sc = device_get_softc(timer_dev); - /* Get the number of times to count */ counts = usec * ((sc->tc.tc_frequency / 1000000) + 1);