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:
parent
49390e758d
commit
e1b5472915
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=260166
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user