1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-23 11:18:54 +00:00

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 <wma@semihalf.com>
Obtained from:	Semihalf
This commit is contained in:
Zbigniew Bodek 2014-01-01 20:35:38 +00:00
parent 49390e758d
commit e1b5472915
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=260166

View File

@ -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);