mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2025-08-18 05:07:00 +02:00
Merge branch 'next' of https://source.denx.de/u-boot/custodians/u-boot-watchdog into next
- misc cyclic infrastructure improvements (Rasmus) - watchdog_reset cleanup (Rasmus) CI: https://dev.azure.com/sr0718/u-boot/_build/results?buildId=369&view=results
This commit is contained in:
commit
e242cd9513
@ -108,26 +108,6 @@ int do_reset(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
|
||||
return 0;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_WATCHDOG)
|
||||
void watchdog_reset(void)
|
||||
{
|
||||
mbar_writeShort(MCF_WTM_WSR, 0x5555);
|
||||
mbar_writeShort(MCF_WTM_WSR, 0xAAAA);
|
||||
}
|
||||
|
||||
int watchdog_disable(void)
|
||||
{
|
||||
mbar_writeShort(MCF_WTM_WCR, 0);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int watchdog_init(void)
|
||||
{
|
||||
mbar_writeShort(MCF_WTM_WCR, MCF_WTM_WCR_EN);
|
||||
return (0);
|
||||
}
|
||||
#endif /* #ifdef CONFIG_WATCHDOG */
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_M5272
|
||||
@ -174,49 +154,6 @@ int print_cpuinfo(void)
|
||||
};
|
||||
#endif /* CONFIG_DISPLAY_CPUINFO */
|
||||
|
||||
#if defined(CONFIG_WATCHDOG)
|
||||
/* Called by macro WATCHDOG_RESET */
|
||||
void watchdog_reset(void)
|
||||
{
|
||||
wdog_t *wdt = (wdog_t *)(MMAP_WDOG);
|
||||
|
||||
out_be16(&wdt->wdog_wcr, 0);
|
||||
}
|
||||
|
||||
int watchdog_disable(void)
|
||||
{
|
||||
wdog_t *wdt = (wdog_t *)(MMAP_WDOG);
|
||||
|
||||
/* reset watchdog counter */
|
||||
out_be16(&wdt->wdog_wcr, 0);
|
||||
/* disable watchdog interrupt */
|
||||
out_be16(&wdt->wdog_wirr, 0);
|
||||
/* disable watchdog timer */
|
||||
out_be16(&wdt->wdog_wrrr, 0);
|
||||
|
||||
puts("WATCHDOG:disabled\n");
|
||||
return (0);
|
||||
}
|
||||
|
||||
int watchdog_init(void)
|
||||
{
|
||||
wdog_t *wdt = (wdog_t *)(MMAP_WDOG);
|
||||
|
||||
/* disable watchdog interrupt */
|
||||
out_be16(&wdt->wdog_wirr, 0);
|
||||
|
||||
/* set timeout and enable watchdog */
|
||||
out_be16(&wdt->wdog_wrrr,
|
||||
(CONFIG_WATCHDOG_TIMEOUT_MSECS * CONFIG_SYS_HZ) / (32768 * 1000) - 1);
|
||||
|
||||
/* reset watchdog counter */
|
||||
out_be16(&wdt->wdog_wcr, 0);
|
||||
|
||||
puts("WATCHDOG:enabled\n");
|
||||
return (0);
|
||||
}
|
||||
#endif /* #ifdef CONFIG_WATCHDOG */
|
||||
|
||||
#endif /* #ifdef CONFIG_M5272 */
|
||||
|
||||
#ifdef CONFIG_M5275
|
||||
@ -243,51 +180,6 @@ int print_cpuinfo(void)
|
||||
};
|
||||
#endif /* CONFIG_DISPLAY_CPUINFO */
|
||||
|
||||
#if defined(CONFIG_WATCHDOG)
|
||||
/* Called by macro WATCHDOG_RESET */
|
||||
void watchdog_reset(void)
|
||||
{
|
||||
wdog_t *wdt = (wdog_t *)(MMAP_WDOG);
|
||||
|
||||
out_be16(&wdt->wsr, 0x5555);
|
||||
out_be16(&wdt->wsr, 0xaaaa);
|
||||
}
|
||||
|
||||
int watchdog_disable(void)
|
||||
{
|
||||
wdog_t *wdt = (wdog_t *)(MMAP_WDOG);
|
||||
|
||||
/* reset watchdog counter */
|
||||
out_be16(&wdt->wsr, 0x5555);
|
||||
out_be16(&wdt->wsr, 0xaaaa);
|
||||
|
||||
/* disable watchdog timer */
|
||||
out_be16(&wdt->wcr, 0);
|
||||
|
||||
puts("WATCHDOG:disabled\n");
|
||||
return (0);
|
||||
}
|
||||
|
||||
int watchdog_init(void)
|
||||
{
|
||||
wdog_t *wdt = (wdog_t *)(MMAP_WDOG);
|
||||
|
||||
/* disable watchdog */
|
||||
out_be16(&wdt->wcr, 0);
|
||||
|
||||
/* set timeout and enable watchdog */
|
||||
out_be16(&wdt->wmr,
|
||||
(CONFIG_WATCHDOG_TIMEOUT_MSECS * CONFIG_SYS_HZ) / (32768 * 1000) - 1);
|
||||
|
||||
/* reset watchdog counter */
|
||||
out_be16(&wdt->wsr, 0x5555);
|
||||
out_be16(&wdt->wsr, 0xaaaa);
|
||||
|
||||
puts("WATCHDOG:enabled\n");
|
||||
return (0);
|
||||
}
|
||||
#endif /* #ifdef CONFIG_WATCHDOG */
|
||||
|
||||
#endif /* #ifdef CONFIG_M5275 */
|
||||
|
||||
#ifdef CONFIG_M5282
|
||||
|
@ -164,21 +164,6 @@ unsigned long get_tbclk(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_WATCHDOG) && !defined(CONFIG_WDT)
|
||||
void watchdog_reset (void)
|
||||
{
|
||||
int re_enable = disable_interrupts();
|
||||
|
||||
/* Reset the 83xx watchdog */
|
||||
volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
|
||||
immr->wdt.swsrr = 0x556c;
|
||||
immr->wdt.swsrr = 0xaa39;
|
||||
|
||||
if (re_enable)
|
||||
enable_interrupts();
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Initializes on-chip MMC controllers.
|
||||
* to override, implement board_mmc_init()
|
||||
|
@ -349,37 +349,6 @@ __weak unsigned long get_tbclk(void)
|
||||
}
|
||||
|
||||
|
||||
#ifndef CONFIG_WDT
|
||||
#if defined(CONFIG_WATCHDOG)
|
||||
#define WATCHDOG_MASK (TCR_WP(63) | TCR_WRC(3) | TCR_WIE)
|
||||
void
|
||||
init_85xx_watchdog(void)
|
||||
{
|
||||
mtspr(SPRN_TCR, (mfspr(SPRN_TCR) & ~WATCHDOG_MASK) |
|
||||
TCR_WP(CFG_WATCHDOG_PRESC) | TCR_WRC(CFG_WATCHDOG_RC));
|
||||
}
|
||||
|
||||
void
|
||||
reset_85xx_watchdog(void)
|
||||
{
|
||||
/*
|
||||
* Clear TSR(WIS) bit by writing 1
|
||||
*/
|
||||
mtspr(SPRN_TSR, TSR_WIS);
|
||||
}
|
||||
|
||||
void
|
||||
watchdog_reset(void)
|
||||
{
|
||||
int re_enable = disable_interrupts();
|
||||
|
||||
reset_85xx_watchdog();
|
||||
if (re_enable)
|
||||
enable_interrupts();
|
||||
}
|
||||
#endif /* CONFIG_WATCHDOG */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Initializes on-chip MMC controllers.
|
||||
* to override, implement board_mmc_init()
|
||||
|
@ -6,4 +6,4 @@
|
||||
# (C) Copyright 2007
|
||||
# Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
|
||||
|
||||
obj-y = cpu.o interrupts.o watchdog.o cache.o
|
||||
obj-y = cpu.o interrupts.o cache.o
|
||||
|
@ -10,6 +10,16 @@
|
||||
#include <net.h>
|
||||
#include <netdev.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/system.h>
|
||||
|
||||
void reset_cpu(void)
|
||||
{
|
||||
/* Address error with SR.BL=1 first. */
|
||||
trigger_address_error();
|
||||
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
int checkcpu(void)
|
||||
{
|
||||
|
@ -1,60 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
#include <cpu_func.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#define WDT_BASE WTCNT
|
||||
|
||||
#define WDT_WD (1 << 6)
|
||||
#define WDT_RST_P (0)
|
||||
#define WDT_RST_M (1 << 5)
|
||||
#define WDT_ENABLE (1 << 7)
|
||||
|
||||
#if defined(CONFIG_WATCHDOG)
|
||||
static unsigned char csr_read(void)
|
||||
{
|
||||
return inb(WDT_BASE + 0x04);
|
||||
}
|
||||
|
||||
static void cnt_write(unsigned char value)
|
||||
{
|
||||
outl((unsigned short)value | 0x5A00, WDT_BASE + 0x00);
|
||||
}
|
||||
|
||||
static void csr_write(unsigned char value)
|
||||
{
|
||||
outl((unsigned short)value | 0xA500, WDT_BASE + 0x04);
|
||||
}
|
||||
|
||||
void watchdog_reset(void)
|
||||
{
|
||||
outl(0x55000000, WDT_BASE + 0x08);
|
||||
}
|
||||
|
||||
int watchdog_init(void)
|
||||
{
|
||||
/* Set overflow time*/
|
||||
cnt_write(0);
|
||||
/* Power on reset */
|
||||
csr_write(WDT_WD|WDT_RST_P|WDT_ENABLE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int watchdog_disable(void)
|
||||
{
|
||||
csr_write(csr_read() & ~WDT_ENABLE);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void reset_cpu(void)
|
||||
{
|
||||
/* Address error with SR.BL=1 first. */
|
||||
trigger_address_error();
|
||||
|
||||
while (1)
|
||||
;
|
||||
}
|
@ -249,7 +249,7 @@ void board_configure_qlms(void)
|
||||
* read the incorrect device ID 0x9700 (reset value) instead of 0x9702
|
||||
* (restored value).
|
||||
*/
|
||||
static void octeon_board_restore_pf(void *ctx)
|
||||
static void octeon_board_restore_pf(struct cyclic_info *c)
|
||||
{
|
||||
union cvmx_spemx_flr_pf_stopreq stopreq;
|
||||
static bool start_initialized[2] = {false, false};
|
||||
@ -357,10 +357,13 @@ int board_late_init(void)
|
||||
board_configure_qlms();
|
||||
|
||||
/* Register cyclic function for PCIe FLR fixup */
|
||||
cyclic = cyclic_register(octeon_board_restore_pf, 100,
|
||||
"pcie_flr_fix", NULL);
|
||||
if (!cyclic)
|
||||
cyclic = calloc(1, sizeof(*cyclic));
|
||||
if (cyclic) {
|
||||
cyclic_register(cyclic, octeon_board_restore_pf, 100,
|
||||
"pcie_flr_fix");
|
||||
} else {
|
||||
printf("Registering of cyclic function failed\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
12
cmd/cyclic.c
12
cmd/cyclic.c
@ -15,14 +15,16 @@
|
||||
#include <time.h>
|
||||
#include <vsprintf.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
struct cyclic_demo_info {
|
||||
struct cyclic_info cyclic;
|
||||
uint delay_us;
|
||||
};
|
||||
|
||||
static void cyclic_demo(void *ctx)
|
||||
static void cyclic_demo(struct cyclic_info *c)
|
||||
{
|
||||
struct cyclic_demo_info *info = ctx;
|
||||
struct cyclic_demo_info *info = container_of(c, struct cyclic_demo_info, cyclic);
|
||||
|
||||
/* Just a small dummy delay here */
|
||||
udelay(info->delay_us);
|
||||
@ -32,7 +34,6 @@ static int do_cyclic_demo(struct cmd_tbl *cmdtp, int flag, int argc,
|
||||
char *const argv[])
|
||||
{
|
||||
struct cyclic_demo_info *info;
|
||||
struct cyclic_info *cyclic;
|
||||
uint time_ms;
|
||||
|
||||
if (argc < 3)
|
||||
@ -48,10 +49,7 @@ static int do_cyclic_demo(struct cmd_tbl *cmdtp, int flag, int argc,
|
||||
info->delay_us = simple_strtoul(argv[2], NULL, 0);
|
||||
|
||||
/* Register demo cyclic function */
|
||||
cyclic = cyclic_register(cyclic_demo, time_ms * 1000, "cyclic_demo",
|
||||
info);
|
||||
if (!cyclic)
|
||||
printf("Registering of cyclic_demo failed\n");
|
||||
cyclic_register(&info->cyclic, cyclic_demo, time_ms * 1000, "cyclic_demo");
|
||||
|
||||
printf("Registered function \"%s\" to be executed all %dms\n",
|
||||
"cyclic_demo", time_ms);
|
||||
|
@ -26,34 +26,22 @@ struct hlist_head *cyclic_get_list(void)
|
||||
return (struct hlist_head *)&gd->cyclic_list;
|
||||
}
|
||||
|
||||
struct cyclic_info *cyclic_register(cyclic_func_t func, uint64_t delay_us,
|
||||
const char *name, void *ctx)
|
||||
void cyclic_register(struct cyclic_info *cyclic, cyclic_func_t func,
|
||||
uint64_t delay_us, const char *name)
|
||||
{
|
||||
struct cyclic_info *cyclic;
|
||||
|
||||
cyclic = calloc(1, sizeof(struct cyclic_info));
|
||||
if (!cyclic) {
|
||||
pr_debug("Memory allocation error\n");
|
||||
return NULL;
|
||||
}
|
||||
memset(cyclic, 0, sizeof(*cyclic));
|
||||
|
||||
/* Store values in struct */
|
||||
cyclic->func = func;
|
||||
cyclic->ctx = ctx;
|
||||
cyclic->name = strdup(name);
|
||||
cyclic->name = name;
|
||||
cyclic->delay_us = delay_us;
|
||||
cyclic->start_time_us = timer_get_us();
|
||||
hlist_add_head(&cyclic->list, cyclic_get_list());
|
||||
|
||||
return cyclic;
|
||||
}
|
||||
|
||||
int cyclic_unregister(struct cyclic_info *cyclic)
|
||||
void cyclic_unregister(struct cyclic_info *cyclic)
|
||||
{
|
||||
hlist_del(&cyclic->list);
|
||||
free(cyclic);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cyclic_run(void)
|
||||
@ -76,7 +64,7 @@ void cyclic_run(void)
|
||||
if (time_after_eq64(now, cyclic->next_call)) {
|
||||
/* Call cyclic function and account it's cpu-time */
|
||||
cyclic->next_call = now + cyclic->delay_us;
|
||||
cyclic->func(cyclic->ctx);
|
||||
cyclic->func(cyclic);
|
||||
cyclic->run_cnt++;
|
||||
cpu_time = timer_get_us() - now;
|
||||
cyclic->cpu_time_us += cpu_time;
|
||||
|
@ -19,20 +19,26 @@ Registering a cyclic function
|
||||
|
||||
To register a cyclic function, use something like this::
|
||||
|
||||
static void cyclic_demo(void *ctx)
|
||||
struct donkey {
|
||||
struct cyclic_info cyclic;
|
||||
void (*say)(const char *s);
|
||||
};
|
||||
|
||||
static void cyclic_demo(struct cyclic_info *c)
|
||||
{
|
||||
/* Just a small dummy delay here */
|
||||
udelay(10);
|
||||
struct donkey *donkey = container_of(c, struct donkey, cyclic);
|
||||
|
||||
donkey->say("Are we there yet?");
|
||||
}
|
||||
|
||||
int board_init(void)
|
||||
|
||||
int donkey_init(void)
|
||||
{
|
||||
struct cyclic_info *cyclic;
|
||||
|
||||
struct donkey *donkey;
|
||||
|
||||
/* Initialize donkey ... */
|
||||
|
||||
/* Register demo cyclic function */
|
||||
cyclic = cyclic_register(cyclic_demo, 10 * 1000, "cyclic_demo", NULL);
|
||||
if (!cyclic)
|
||||
printf("Registering of cyclic_demo failed\n");
|
||||
cyclic_register(&donkey->cyclic, cyclic_demo, 10 * 1000, "cyclic_demo");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -291,9 +291,9 @@ void ns16550_putc(struct ns16550 *com_port, char c)
|
||||
serial_out(c, &com_port->thr);
|
||||
|
||||
/*
|
||||
* Call watchdog_reset() upon newline. This is done here in putc
|
||||
* Call schedule() upon newline. This is done here in putc
|
||||
* since the environment code uses a single puts() to print the complete
|
||||
* environment upon "printenv". So we can't put this watchdog call
|
||||
* environment upon "printenv". So we can't put this schedule call
|
||||
* in puts().
|
||||
*/
|
||||
if (c == '\n')
|
||||
@ -390,9 +390,9 @@ static int ns16550_serial_putc(struct udevice *dev, const char ch)
|
||||
serial_out(ch, &com_port->thr);
|
||||
|
||||
/*
|
||||
* Call watchdog_reset() upon newline. This is done here in putc
|
||||
* Call schedule() upon newline. This is done here in putc
|
||||
* since the environment code uses a single puts() to print the complete
|
||||
* environment upon "printenv". So we can't put this watchdog call
|
||||
* environment upon "printenv". So we can't put this schedule call
|
||||
* in puts().
|
||||
*/
|
||||
if (ch == '\n')
|
||||
|
@ -17,17 +17,20 @@
|
||||
#include <asm/global_data.h>
|
||||
#include <dm/device-internal.h>
|
||||
#include <dm/lists.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#define WATCHDOG_TIMEOUT_SECS (CONFIG_WATCHDOG_TIMEOUT_MSECS / 1000)
|
||||
|
||||
struct wdt_priv {
|
||||
/* The udevice owning this wdt_priv. */
|
||||
struct udevice *dev;
|
||||
/* Timeout, in seconds, to configure this device to. */
|
||||
u32 timeout;
|
||||
/*
|
||||
* Time, in milliseconds, between calling the device's ->reset()
|
||||
* method from watchdog_reset().
|
||||
* method from schedule().
|
||||
*/
|
||||
ulong reset_period;
|
||||
/*
|
||||
@ -40,18 +43,17 @@ struct wdt_priv {
|
||||
/* autostart */
|
||||
bool autostart;
|
||||
|
||||
struct cyclic_info *cyclic;
|
||||
struct cyclic_info cyclic;
|
||||
};
|
||||
|
||||
static void wdt_cyclic(void *ctx)
|
||||
static void wdt_cyclic(struct cyclic_info *c)
|
||||
{
|
||||
struct udevice *dev = ctx;
|
||||
struct wdt_priv *priv;
|
||||
struct wdt_priv *priv = container_of(c, struct wdt_priv, cyclic);
|
||||
struct udevice *dev = priv->dev;
|
||||
|
||||
if (!device_active(dev))
|
||||
return;
|
||||
|
||||
priv = dev_get_uclass_priv(dev);
|
||||
if (!priv->running)
|
||||
return;
|
||||
|
||||
@ -121,24 +123,20 @@ int wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags)
|
||||
struct wdt_priv *priv = dev_get_uclass_priv(dev);
|
||||
char str[16];
|
||||
|
||||
priv->running = true;
|
||||
|
||||
memset(str, 0, 16);
|
||||
if (IS_ENABLED(CONFIG_WATCHDOG)) {
|
||||
if (priv->running)
|
||||
cyclic_unregister(&priv->cyclic);
|
||||
|
||||
/* Register the watchdog driver as a cyclic function */
|
||||
priv->cyclic = cyclic_register(wdt_cyclic,
|
||||
priv->reset_period * 1000,
|
||||
dev->name, dev);
|
||||
if (!priv->cyclic) {
|
||||
printf("cyclic_register for %s failed\n",
|
||||
dev->name);
|
||||
return -ENODEV;
|
||||
} else {
|
||||
snprintf(str, 16, "every %ldms",
|
||||
priv->reset_period);
|
||||
}
|
||||
cyclic_register(&priv->cyclic, wdt_cyclic,
|
||||
priv->reset_period * 1000,
|
||||
dev->name);
|
||||
|
||||
snprintf(str, 16, "every %ldms", priv->reset_period);
|
||||
}
|
||||
|
||||
priv->running = true;
|
||||
printf("WDT: Started %s with%s servicing %s (%ds timeout)\n",
|
||||
dev->name, IS_ENABLED(CONFIG_WATCHDOG) ? "" : "out",
|
||||
str, (u32)lldiv(timeout_ms, 1000));
|
||||
@ -159,6 +157,9 @@ int wdt_stop(struct udevice *dev)
|
||||
if (ret == 0) {
|
||||
struct wdt_priv *priv = dev_get_uclass_priv(dev);
|
||||
|
||||
if (IS_ENABLED(CONFIG_WATCHDOG) && priv->running)
|
||||
cyclic_unregister(&priv->cyclic);
|
||||
|
||||
priv->running = false;
|
||||
}
|
||||
|
||||
@ -221,21 +222,6 @@ int wdt_expire_now(struct udevice *dev, ulong flags)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_WATCHDOG)
|
||||
/*
|
||||
* Called by macro WATCHDOG_RESET. This function be called *very* early,
|
||||
* so we need to make sure, that the watchdog driver is ready before using
|
||||
* it in this function.
|
||||
*/
|
||||
void watchdog_reset(void)
|
||||
{
|
||||
/*
|
||||
* Empty function for now. The actual WDT handling is now done in
|
||||
* the cyclic function instead.
|
||||
*/
|
||||
}
|
||||
#endif
|
||||
|
||||
static int wdt_pre_probe(struct udevice *dev)
|
||||
{
|
||||
u32 timeout = WATCHDOG_TIMEOUT_SECS;
|
||||
@ -257,12 +243,13 @@ static int wdt_pre_probe(struct udevice *dev)
|
||||
autostart = true;
|
||||
}
|
||||
priv = dev_get_uclass_priv(dev);
|
||||
priv->dev = dev;
|
||||
priv->timeout = timeout;
|
||||
priv->reset_period = reset_period;
|
||||
priv->autostart = autostart;
|
||||
/*
|
||||
* Pretend this device was last reset "long" ago so the first
|
||||
* watchdog_reset will actually call its ->reset method.
|
||||
* schedule() will actually call its ->reset method.
|
||||
*/
|
||||
priv->next_reset = get_timer(0);
|
||||
|
||||
|
@ -18,7 +18,6 @@
|
||||
* struct cyclic_info - Information about cyclic execution function
|
||||
*
|
||||
* @func: Function to call periodically
|
||||
* @ctx: Context pointer to get passed to this function
|
||||
* @name: Name of the cyclic function, e.g. shown in the commands
|
||||
* @delay_ns: Delay is ns after which this function shall get executed
|
||||
* @start_time_us: Start time in us, when this function started its execution
|
||||
@ -27,11 +26,13 @@
|
||||
* @next_call: Next time in us, when the function shall be executed again
|
||||
* @list: List node
|
||||
* @already_warned: Flag that we've warned about exceeding CPU time usage
|
||||
*
|
||||
* When !CONFIG_CYCLIC, this struct is empty.
|
||||
*/
|
||||
struct cyclic_info {
|
||||
void (*func)(void *ctx);
|
||||
void *ctx;
|
||||
char *name;
|
||||
#if defined(CONFIG_CYCLIC)
|
||||
void (*func)(struct cyclic_info *c);
|
||||
const char *name;
|
||||
uint64_t delay_us;
|
||||
uint64_t start_time_us;
|
||||
uint64_t cpu_time_us;
|
||||
@ -39,31 +40,34 @@ struct cyclic_info {
|
||||
uint64_t next_call;
|
||||
struct hlist_node list;
|
||||
bool already_warned;
|
||||
#endif
|
||||
};
|
||||
|
||||
/** Function type for cyclic functions */
|
||||
typedef void (*cyclic_func_t)(void *ctx);
|
||||
typedef void (*cyclic_func_t)(struct cyclic_info *c);
|
||||
|
||||
#if defined(CONFIG_CYCLIC)
|
||||
/**
|
||||
* cyclic_register - Register a new cyclic function
|
||||
*
|
||||
* @cyclic: Cyclic info structure
|
||||
* @func: Function to call periodically
|
||||
* @delay_us: Delay is us after which this function shall get executed
|
||||
* @name: Cyclic function name/id
|
||||
* @ctx: Context to pass to the function
|
||||
* @return: pointer to cyclic_struct if OK, NULL on error
|
||||
*
|
||||
* The function @func will be called with @cyclic as its
|
||||
* argument. @cyclic will usually be embedded in some device-specific
|
||||
* structure, which the callback can retrieve using container_of().
|
||||
*/
|
||||
struct cyclic_info *cyclic_register(cyclic_func_t func, uint64_t delay_us,
|
||||
const char *name, void *ctx);
|
||||
void cyclic_register(struct cyclic_info *cyclic, cyclic_func_t func,
|
||||
uint64_t delay_us, const char *name);
|
||||
|
||||
/**
|
||||
* cyclic_unregister - Unregister a cyclic function
|
||||
*
|
||||
* @cyclic: Pointer to cyclic_struct of the function that shall be removed
|
||||
* @return: 0 if OK, -ve on error
|
||||
*/
|
||||
int cyclic_unregister(struct cyclic_info *cyclic);
|
||||
void cyclic_unregister(struct cyclic_info *cyclic);
|
||||
|
||||
/**
|
||||
* cyclic_unregister_all() - Clean up cyclic functions
|
||||
@ -97,17 +101,14 @@ void cyclic_run(void);
|
||||
*/
|
||||
void schedule(void);
|
||||
#else
|
||||
static inline struct cyclic_info *cyclic_register(cyclic_func_t func,
|
||||
uint64_t delay_us,
|
||||
const char *name,
|
||||
void *ctx)
|
||||
|
||||
static inline void cyclic_register(struct cyclic_info *cyclic, cyclic_func_t func,
|
||||
uint64_t delay_us, const char *name)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline int cyclic_unregister(struct cyclic_info *cyclic)
|
||||
static inline void cyclic_unregister(struct cyclic_info *cyclic)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void cyclic_run(void)
|
||||
|
@ -40,7 +40,4 @@ int init_func_watchdog_reset(void);
|
||||
void hw_watchdog_init(void);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_MPC85xx)
|
||||
void init_85xx_watchdog(void);
|
||||
#endif
|
||||
#endif /* _WATCHDOG_H_ */
|
||||
|
@ -12,22 +12,27 @@
|
||||
#include <linux/delay.h>
|
||||
|
||||
/* Test that cyclic function is called */
|
||||
static bool cyclic_active = false;
|
||||
static struct cyclic_test {
|
||||
struct cyclic_info cyclic;
|
||||
bool called;
|
||||
} cyclic_test;
|
||||
|
||||
static void cyclic_test(void *ctx)
|
||||
static void test_cb(struct cyclic_info *c)
|
||||
{
|
||||
cyclic_active = true;
|
||||
struct cyclic_test *t = container_of(c, struct cyclic_test, cyclic);
|
||||
t->called = true;
|
||||
}
|
||||
|
||||
static int dm_test_cyclic_running(struct unit_test_state *uts)
|
||||
{
|
||||
cyclic_active = false;
|
||||
ut_assertnonnull(cyclic_register(cyclic_test, 10 * 1000, "cyclic_demo",
|
||||
NULL));
|
||||
cyclic_test.called = false;
|
||||
cyclic_register(&cyclic_test.cyclic, test_cb, 10 * 1000, "cyclic_test");
|
||||
|
||||
/* Execute all registered cyclic functions */
|
||||
schedule();
|
||||
ut_asserteq(true, cyclic_active);
|
||||
ut_asserteq(true, cyclic_test.called);
|
||||
|
||||
cyclic_unregister(&cyclic_test.cyclic);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user