mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-11 14:10:34 +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;
|
struct timecounter tc;
|
||||||
bool et_enabled;
|
bool et_enabled;
|
||||||
struct eventtimer et;
|
struct eventtimer et;
|
||||||
|
int timer_initialized;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Read/Write macros for Timer used as timecounter */
|
/* Read/Write macros for Timer used as timecounter */
|
||||||
@ -198,6 +199,8 @@ sp804_timer_attach(device_t dev)
|
|||||||
int rid = 0;
|
int rid = 0;
|
||||||
int i;
|
int i;
|
||||||
uint32_t id, reg;
|
uint32_t id, reg;
|
||||||
|
phandle_t node;
|
||||||
|
pcell_t clock;
|
||||||
|
|
||||||
sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
|
sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
|
||||||
if (sc->mem_res == NULL) {
|
if (sc->mem_res == NULL) {
|
||||||
@ -215,8 +218,12 @@ sp804_timer_attach(device_t dev)
|
|||||||
return (ENXIO);
|
return (ENXIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: get frequency from FDT */
|
|
||||||
sc->sysclk_freq = DEFAULT_FREQUENCY;
|
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 */
|
/* Setup and enable the timer */
|
||||||
if (bus_setup_intr(dev, sc->irq_res, INTR_TYPE_CLK,
|
if (bus_setup_intr(dev, sc->irq_res, INTR_TYPE_CLK,
|
||||||
@ -234,8 +241,8 @@ sp804_timer_attach(device_t dev)
|
|||||||
/*
|
/*
|
||||||
* Timer 1, timecounter
|
* Timer 1, timecounter
|
||||||
*/
|
*/
|
||||||
sc->tc.tc_frequency = DEFAULT_FREQUENCY;
|
sc->tc.tc_frequency = sc->sysclk_freq;
|
||||||
sc->tc.tc_name = "SP804 Timecouter";
|
sc->tc.tc_name = "SP804 Time Counter";
|
||||||
sc->tc.tc_get_timecount = sp804_timer_tc_get_timecount;
|
sc->tc.tc_get_timecount = sp804_timer_tc_get_timecount;
|
||||||
sc->tc.tc_poll_pps = NULL;
|
sc->tc.tc_poll_pps = NULL;
|
||||||
sc->tc.tc_counter_mask = ~0u;
|
sc->tc.tc_counter_mask = ~0u;
|
||||||
@ -283,6 +290,8 @@ sp804_timer_attach(device_t dev)
|
|||||||
|
|
||||||
device_printf(dev, "PrimeCell ID: %08x\n", id);
|
device_printf(dev, "PrimeCell ID: %08x\n", id);
|
||||||
|
|
||||||
|
sc->timer_initialized = 1;
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -309,10 +318,18 @@ DELAY(int usec)
|
|||||||
uint32_t first, last;
|
uint32_t first, last;
|
||||||
device_t timer_dev;
|
device_t timer_dev;
|
||||||
struct sp804_timer_softc *sc;
|
struct sp804_timer_softc *sc;
|
||||||
|
int timer_initialized = 0;
|
||||||
|
|
||||||
timer_dev = devclass_get_device(sp804_timer_devclass, 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
|
* Timer is not initialized yet
|
||||||
*/
|
*/
|
||||||
@ -323,8 +340,6 @@ DELAY(int usec)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sc = device_get_softc(timer_dev);
|
|
||||||
|
|
||||||
/* Get the number of times to count */
|
/* Get the number of times to count */
|
||||||
counts = usec * ((sc->tc.tc_frequency / 1000000) + 1);
|
counts = usec * ((sc->tc.tc_frequency / 1000000) + 1);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user