/*------------------------------------------------------------------------------------------*\ * * Copyright (C) 2006 AVM GmbH * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA \*------------------------------------------------------------------------------------------*/ #if defined(CONFIG_AVM_WATCHDOG) /*-----------------------------------------------------------------------------------------------*\ \*-----------------------------------------------------------------------------------------------*/ #include #include #include #include #include #include #include #include #include #include #include /*--- #include ---*/ /*--- #include ---*/ #include /*--- #include ---*/ #include /*-----------------------------------------------------------------------------------------------*\ \*-----------------------------------------------------------------------------------------------*/ #if defined(CONFIG_ARM) #define __printk printk #endif /*--- #define AVM_WATCHDOG_DEBUG ---*/ #if defined(AVM_WATCHDOG_DEBUG) #define DBG(...) printk(KERN_INFO __VA_ARGS__) #else /*--- #if defined(AVM_WATCHDOG_DEBUG) ---*/ #define DBG(...) #endif /*--- #else ---*/ /*--- #if defined(AVM_WATCHDOG_DEBUG) ---*/ #include "avm_sammel.h" #include "ar7wdt.h" /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ struct _ar7wdt_data ar7wdt_data; struct timer_list ar7wdt_timer; /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static void AVM_WATCHDOG_timer_handler(unsigned long); static struct semaphore ar7wdt_sema; extern int ar7wdt_no_reboot; /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static void AVM_WATCHDOG_timer_handler_action(unsigned int handle); volatile unsigned int AVM_WATCHDOG_locked = 0; volatile unsigned int AVM_WATCHDOG_locked_action = 0; #define AVM_WATCHDOG_LOCK() if(down_interruptible(&ar7wdt_sema)) { \ return -ERESTARTSYS; \ } else { \ AVM_WATCHDOG_locked = 1; \ } #define AVM_WATCHDOG_LOCK_VOID() if(down_interruptible(&ar7wdt_sema)) { \ return; \ } else { \ AVM_WATCHDOG_locked = 1; \ } #define AVM_WATCHDOG_UNLOCK() { \ unsigned int i; \ for(i = 0 ; AVM_WATCHDOG_locked_action ; i++) { \ if(i == 32) i = 0; \ if(AVM_WATCHDOG_locked_action & (1 << i)) \ AVM_WATCHDOG_timer_handler_action(i); \ } \ AVM_WATCHDOG_locked = 0; \ up(&ar7wdt_sema); \ } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static int _AVM_WATCHDOG_atoi(char *p) { int value = 0; while(p && *p && ((*p < '0') || (*p > '9'))) p++; while(p && *p) { if(*p >= '0' && *p <= '9') { value *= 10; value += *p - '0'; } else { break; } p++; } return value; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ #define AVM_WATCHDOG_DEL_TIMER 0x01 #define AVM_WATCHDOG_SET_TIMER 0x02 static void _AVM_WATCHDOG_ctrl_timer(int flags, int i) { struct timer_list *timer; int default_time; DBG(KERN_INFO "_AVM_WATCHDOG_ctrl_timer(flags=0x%x, handle=%d)\n", flags, i + 1); if(i == -1) { timer = &ar7wdt_timer; default_time = 20; } else { timer = &(ar7wdt_data.appl[i].Timer); default_time = ar7wdt_data.appl[i].default_time; } if(flags & AVM_WATCHDOG_DEL_TIMER) { del_timer(timer); } if(flags & AVM_WATCHDOG_SET_TIMER) { timer->expires = jiffies + HZ * default_time; add_timer(timer); } } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void AVM_WATCHDOG_init(void) { DBG(KERN_INFO "AVM_WATCHDOG_init:\n"); memset(&ar7wdt_data, 0x00, sizeof(ar7wdt_data)); sema_init(&ar7wdt_sema, 1); init_timer(&ar7wdt_timer); ar7wdt_timer.function = AVM_WATCHDOG_timer_handler; ar7wdt_timer.data = -1; _AVM_WATCHDOG_ctrl_timer(AVM_WATCHDOG_SET_TIMER, -1); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void AVM_WATCHDOG_deinit(void) { DBG(KERN_INFO "AVM_WATCHDOG_deinit:\n"); _AVM_WATCHDOG_ctrl_timer(AVM_WATCHDOG_DEL_TIMER, -1); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int AVM_WATCHDOG_find_handle(char *name, int len) { int i; DBG(KERN_ERR "AVM_WATCHDOG_find_handle('%s', len=%u):\n", name, len); for( i = 0 ; i < MAX_WDT_APPLS ; i++) { if(ar7wdt_data.mask & (1 << i)) { if(!strcmp(ar7wdt_data.appl[i].Name, name)) { DBG(" handle=%u\n", i + 1); return i + 1; } } } DBG(" handle= not found\n"); return 0; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int AVM_WATCHDOG_strip_name(char **name, int len) { DBG(KERN_ERR "AVM_WATCHDOG_strip_name('%s', len=%u): ", *name, len); while((*name)[len - 1] == '\n' || (*name)[len - 1] == '\r') (*name)[len - 1] = '\0', len = strlen(*name); len = min(len, MAX_WDT_NAME_LEN - 1); (*name)[len] = '\0'; len = strlen(*name); DBG("-->('%s', len=%u)", *name, len); while(len && (**name == ' ' || **name == '\t' || **name == '\n' || **name == '\r')) (*name)++, len--; DBG("-->('%s', len=%u):\n", *name, len); return len; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static void AVM_WATCHDOG_timer_init_ctrl_handler(unsigned long _handle) { if(ar7wdt_no_reboot == 0) { panic("ar7wdt_hw_reboot: init sequence hangs !\n"); } } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int AVM_WATCHDOG_init_start(int handle, char *name, int len) { /*--- ignore handle ---*/ unsigned int Sekunden = _AVM_WATCHDOG_atoi(name); if(Sekunden == 0) Sekunden = 120; /*--- 2 Minuten ---*/ init_waitqueue_head(&(ar7wdt_data.appl[MAX_WDT_APPLS].wait_queue)); ar7wdt_data.appl[MAX_WDT_APPLS].fasync = NULL; ar7wdt_data.appl[MAX_WDT_APPLS].default_time = Sekunden; ar7wdt_data.appl[MAX_WDT_APPLS].Timer.function = AVM_WATCHDOG_timer_init_ctrl_handler; ar7wdt_data.appl[MAX_WDT_APPLS].Timer.data = MAX_WDT_APPLS + 1; /*--- handle ---*/ init_timer(&(ar7wdt_data.appl[MAX_WDT_APPLS].Timer)); strcpy(ar7wdt_data.appl[MAX_WDT_APPLS].Name, "init-ctrl"); #ifdef CONFIG_PRINTK printk("AVM_WATCHDOG: System Init UEberwachung %u Sekunden\n", Sekunden); #endif /*--- #ifdef CONFIG_PRINTK ---*/ _AVM_WATCHDOG_ctrl_timer(AVM_WATCHDOG_SET_TIMER, MAX_WDT_APPLS); return MAX_WDT_APPLS + 1; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int AVM_WATCHDOG_init_done(int handle, char *name, int len) { #ifdef CONFIG_PRINTK printk("AVM_WATCHDOG: System Init UEberwachung abgeschlossen (%lu ms noch verfuegbar)\n", 10 * (ar7wdt_data.appl[MAX_WDT_APPLS].Timer.expires - jiffies)); #endif /*--- #ifdef CONFIG_PRINTK ---*/ _AVM_WATCHDOG_ctrl_timer(AVM_WATCHDOG_DEL_TIMER, MAX_WDT_APPLS); return handle; } /*-------------------------------------------------------------------------------------*\ \*-------------------------------------------------------------------------------------*/ void AVM_WATCHDOG_ungraceful_release(int handle) { DBG(KERN_INFO "AVM_WATCHDOG_ungraceful_release(%u)\n", handle); if(handle < 1 || handle > MAX_WDT_APPLS) { DBG(KERN_ERR "AVM_WATCHDOG_ungraceful_release(hdl=%u): invalid handle\n", handle); return; } handle--; if (ar7wdt_data.mask & (1 << handle)) { #ifdef CONFIG_PRINTK printk(KERN_EMERG "AVM_WATCHDOG_ungraceful_release: handle %u (%s) still registered!\n", handle + 1, ar7wdt_data.appl[handle].Name); #endif /*--- #ifdef CONFIG_PRINTK ---*/ } } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int AVM_WATCHDOG_register(int handle, char *name, int len) { int i; DBG(KERN_INFO "AVM_WATCHDOG_register(%s): start\n", name); len = AVM_WATCHDOG_strip_name(&name, len); AVM_WATCHDOG_LOCK(); for( i = 1 ; i < MAX_WDT_APPLS ; i++) { if(ar7wdt_data.mask & (1 << i)) { if(strcmp(ar7wdt_data.appl[i].Name, name)) continue; DBG(KERN_INFO "AVM_WATCHDOG_register(%s): already registered (accept) handle=%u\n", name, i + 1); AVM_WATCHDOG_UNLOCK(); return i + 1; } } DBG(KERN_INFO "AVM_WATCHDOG_register(%s): not yet registered\n", name); for( i = 1 ; i < MAX_WDT_APPLS ; i++) { if(ar7wdt_data.mask & (1 << i)) { continue; } ar7wdt_data.mask |= (1 << i); ar7wdt_data.triggered &= ~(1 << i); ar7wdt_data.requested |= (1 << i); init_waitqueue_head(&(ar7wdt_data.appl[i].wait_queue)); ar7wdt_data.appl[i].fasync = NULL; ar7wdt_data.appl[i].default_time = WDT_DEFAULT_TIME; ar7wdt_data.appl[i].Timer.function = AVM_WATCHDOG_timer_handler; ar7wdt_data.appl[i].Timer.data = i + 1; /*--- handle ---*/ init_timer(&(ar7wdt_data.appl[i].Timer)); strncpy(ar7wdt_data.appl[i].Name, name, len); ar7wdt_data.appl[i].Name[len] = '\0'; _AVM_WATCHDOG_ctrl_timer(AVM_WATCHDOG_SET_TIMER, i); DBG(KERN_INFO "AVM_WATCHDOG_register(%s): handle=%u mask=0x%08x\n", name, i + 1, ar7wdt_data.mask); AVM_WATCHDOG_UNLOCK(); return i + 1; } DBG(KERN_ERR "AVM_WATCHDOG_register(%s): not registered, too many appls\n", name); AVM_WATCHDOG_UNLOCK(); return -EUSERS; /*--- to many users ---*/ } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ struct fasync_struct **AVM_WATCHDOG_get_fasync_ptr(int handle) { if(handle < 1 || handle > MAX_WDT_APPLS) { DBG(KERN_ERR "AVM_WATCHDOG_get_fasync_ptr(hdl=%u): invalid handle\n", handle); return NULL; /*--- io error ---*/ } handle--; if((ar7wdt_data.mask & (1 << handle)) == 0) { DBG(KERN_ERR "AVM_WATCHDOG_get_fasync_ptr(hdl=%u): invalid handle (not set in mask)\n", handle + 1); return NULL; /*--- io error ---*/ } return &(ar7wdt_data.appl[handle].fasync); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ wait_queue_head_t *AVM_WATCHDOG_get_wait_queue(int handle) { if(handle < 1 || handle > MAX_WDT_APPLS) { DBG(KERN_ERR "AVM_WATCHDOG_get_wait_queue(hdl=%u): invalid handle\n", handle); return NULL; /*--- io error ---*/ } handle--; if((ar7wdt_data.mask & (1 << handle)) == 0) { DBG(KERN_ERR "AVM_WATCHDOG_get_wait_queue(hdl=%u): invalid handle (not set in mask)\n", handle + 1); return NULL; /*--- io error ---*/ } return &(ar7wdt_data.appl[handle].wait_queue); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int AVM_WATCHDOG_poll(int handle) { if(handle < 1 || handle > MAX_WDT_APPLS) { DBG(KERN_ERR "AVM_WATCHDOG_poll(hdl=%u): invalid handle\n", handle); return -EINVAL; /*--- inval argument ---*/ } handle--; if((ar7wdt_data.mask & (1 << handle)) == 0) { DBG(KERN_ERR "AVM_WATCHDOG_poll(hdl=%u): invalid handle (not set in mask)\n", handle + 1); return -EINVAL; /*--- inval argument ---*/ } return (ar7wdt_data.requested & (1 << handle)) ? 1 : 0; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int AVM_WATCHDOG_release(int handle, char *name, int len) { DBG(KERN_INFO "AVM_WATCHDOG_release(hdl=%u): name='%s', len=%u\n", handle, name, len); len = AVM_WATCHDOG_strip_name(&name, len); if(handle < 1 || handle > MAX_WDT_APPLS) { DBG(KERN_ERR "AVM_WATCHDOG_release(hdl=%u): invalid handle\n", handle); return -EINVAL; /*--- inval argument ---*/ } handle--; if(len) { if(strcmp(name, ar7wdt_data.appl[handle].Name)) { DBG(KERN_INFO "AVM_WATCHDOG_release(hdl=%u): name='%s', len=%u (name and handle to not correspond)\n", handle, name, len); handle = AVM_WATCHDOG_find_handle(name, len); if(handle == 0) { DBG(KERN_ERR "AVM_WATCHDOG_release(hdl=%u): invalid name\n", handle + 1); return -EINVAL; /*--- inval argument ---*/ } handle--; } } if((ar7wdt_data.mask & (1 << handle)) == 0) { DBG(KERN_ERR "AVM_WATCHDOG_release(hdl=%u): invalid handle (not set in mask)\n", handle + 1); return -EINVAL; /*--- inval argument ---*/ } /*--- timer stopen ---*/ AVM_WATCHDOG_LOCK(); _AVM_WATCHDOG_ctrl_timer(AVM_WATCHDOG_DEL_TIMER, handle); ar7wdt_data.mask &= ~(1 << handle); ar7wdt_data.requested &= ~(1 << handle); ar7wdt_data.states &= ~(1 << handle); ar7wdt_data.triggered &= ~(1 << handle); AVM_WATCHDOG_UNLOCK(); DBG(KERN_INFO "AVM_WATCHDOG_release(hdl=%u): success\n", handle + 1); return 0; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int AVM_WATCHDOG_set_timeout(int handle, char *time, int len) { if(handle < 1 || handle > MAX_WDT_APPLS) { DBG(KERN_ERR "AVM_WATCHDOG_set_timeout(hdl=%u): invalid handle\n", handle); return -EINVAL; /*--- inval argument ---*/ } handle--; if((ar7wdt_data.mask & (1 << handle)) == 0) { DBG(KERN_ERR "AVM_WATCHDOG_set_timeout(hdl=%u): invalid handle\n", handle + 1); return -EINVAL; /*--- inval argument ---*/ } AVM_WATCHDOG_LOCK(); ar7wdt_data.appl[handle].default_time = _AVM_WATCHDOG_atoi(time) / 2; _AVM_WATCHDOG_ctrl_timer(AVM_WATCHDOG_SET_TIMER | AVM_WATCHDOG_DEL_TIMER, handle); AVM_WATCHDOG_UNLOCK(); DBG(KERN_INFO "AVM_WATCHDOG_set_timeout(hdl=%u): success (new timeout=%u)\n", handle + 1, ar7wdt_data.appl[handle].default_time); return handle + 1; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int AVM_WATCHDOG_trigger(int handle, char *time, int len) { if(handle < 1 || handle > MAX_WDT_APPLS) { DBG(KERN_ERR "AVM_WATCHDOG_trigger(hdl=%u): invalid handle\n", handle); return -EINVAL; /*--- inval argument ---*/ } handle--; if((ar7wdt_data.mask & (1 << handle)) == 0) { DBG(KERN_ERR "AVM_WATCHDOG_trigger(hdl=%u): invalid handle (not set in mask)\n", handle + 1); return -EINVAL; /*--- inval argument ---*/ } AVM_WATCHDOG_LOCK(); ar7wdt_data.triggered |= (1 << handle); ar7wdt_data.states &= ~(1 << handle); /*--- ar7wdt_data.appl[i].default_time ---*/ /*--- timer neu aufsetzen ---*/ _AVM_WATCHDOG_ctrl_timer(AVM_WATCHDOG_DEL_TIMER | AVM_WATCHDOG_SET_TIMER, handle); AVM_WATCHDOG_UNLOCK(); AVM_WATCHDOG_check_all_triggered(); DBG(KERN_ERR "AVM_WATCHDOG_trigger(hdl=%u): success\n", handle + 1); return handle + 1; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int AVM_WATCHDOG_disable(int handle, char *time, int len) { int i; printk(KERN_INFO "AVM_WATCHDOG_disable()\n"); printk(KERN_INFO "registered appls:\n"); AVM_WATCHDOG_LOCK(); for (i = 0; i < MAX_WDT_APPLS; i++) { if((ar7wdt_data.mask & (1 << i))) { _AVM_WATCHDOG_ctrl_timer(AVM_WATCHDOG_DEL_TIMER, i); ar7wdt_data.mask &= ~(1 << i); ar7wdt_data.requested &= ~(1 << i); ar7wdt_data.states &= ~(1 << i); ar7wdt_data.triggered &= ~(1 << i); printk(KERN_INFO " hdl=%u, name=%s, disabled.\n", i + 1, ar7wdt_data.appl[i].Name); } } AVM_WATCHDOG_UNLOCK(); _AVM_WATCHDOG_ctrl_timer(AVM_WATCHDOG_DEL_TIMER, -1); ar7wdt_hw_deinit(); ar7wdt_no_reboot = 3; return 1; /*--- sonst Endlosschleife, weil private_data == 0 ---*/ } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int AVM_WATCHDOG_read(int handle, char *Buffer, int max_len) { if(handle < 1 || handle > MAX_WDT_APPLS) { DBG(KERN_ERR "AVM_WATCHDOG_read(hdl=%u): invalid handle\n", handle); return -EINVAL; /*--- inval argument ---*/ } handle--; if((ar7wdt_data.mask & (1 << handle)) == 0) { DBG(KERN_ERR "AVM_WATCHDOG_read(hdl=%u): invalid handle (not set in mask)\n", handle + 1); return -EINVAL; /*--- inval argument ---*/ } if((ar7wdt_data.requested & (1 << handle)) == 0) { Buffer[0] = '\0'; DBG(KERN_INFO "AVM_WATCHDOG_read(hdl=%u): no request\n", handle + 1); return handle + 1; } AVM_WATCHDOG_LOCK(); ar7wdt_data.requested &= ~(1 << handle); max_len = min(max_len - 1, (int)sizeof("alive ?")); strncpy(Buffer, "alive ?", max_len); Buffer[max_len] = '\0'; AVM_WATCHDOG_UNLOCK(); DBG(KERN_INFO "AVM_WATCHDOG_read(hdl=%u): request='%s'\n", handle + 1, Buffer); return handle + 1; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int AVM_WATCHDOG_reboot(int handle) { if(handle < 1 || handle > MAX_WDT_APPLS) { DBG(KERN_ERR "AVM_WATCHDOG_reboot(hdl=%u): invalid handle\n", handle); return -EINVAL; /*--- inval argument ---*/ } handle--; if((ar7wdt_data.mask & (1 << handle)) == 0) { DBG(KERN_ERR "AVM_WATCHDOG_reboot(hdl=%u): invalid handle (not set in mask)\n", handle + 1); return -EINVAL; /*--- inval argument ---*/ } if(ar7wdt_data.states & (1 << handle)) { int i; __printk(KERN_EMERG "AVM_WATCHDOG_reboot(hdl=%u, name=%s): reboot\n", handle + 1, ar7wdt_data.appl[handle].Name); __printk(KERN_EMERG "registered appls:\n"); for (i = 0; i < MAX_WDT_APPLS; i++) { if((ar7wdt_data.mask & (1 << i))) { __printk(KERN_EMERG " hdl=%u, name=%s\n", i + 1, ar7wdt_data.appl[i].Name); } } if(ar7wdt_no_reboot == 0) { panic("ar7wdt_hw_reboot: watchdog expired\n"); } } printk(KERN_ERR "AVM_WATCHDOG_reboot(hdl=%u): timer not triggered\n", handle + 1); return 0; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void AVM_WATCHDOG_check_all_triggered(void) { int i; unsigned int mask = 0; unsigned int trigger = 0; AVM_WATCHDOG_LOCK_VOID(); for( i = 0 ; i < MAX_WDT_APPLS ; i++) { if(ar7wdt_data.mask & (1 << i)) { mask |= 1 << i; if(ar7wdt_data.triggered & (1 << i)) { trigger |= 1 << i; } } } if(mask == trigger) { ar7wdt_data.triggered = 0; ar7wdt_hw_trigger(); } else { DBG(KERN_INFO "AVM_WATCHDOG_check_all_triggered(): not triggered mask 0x%x\n", mask ^ trigger); } AVM_WATCHDOG_UNLOCK(); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static void AVM_WATCHDOG_timer_handler_action(unsigned int handle) { ar7wdt_data.states |= 1 << handle; ar7wdt_data.requested |= 1 << handle; if(ar7wdt_data.appl[handle].fasync) { kill_fasync(&(ar7wdt_data.appl[handle].fasync), SIGIO, POLL_IN); } else { wake_up_interruptible(&(ar7wdt_data.appl[handle].wait_queue)); } _AVM_WATCHDOG_ctrl_timer(AVM_WATCHDOG_SET_TIMER, handle); AVM_WATCHDOG_locked_action &= ~(1 << handle); /*--- AVM_WATCHDOG_UNLOCK(); ---*/ DBG(KERN_INFO "AVM_WATCHDOG_timer_handler(hdl=%u): timer triggered once\n", handle + 1); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static void AVM_WATCHDOG_timer_handler(unsigned long _handle) { int handle = (int)_handle; DBG(KERN_INFO "AVM_WATCHDOG_timer_handler(hdl=%d)\n", handle); if(handle == -1) { _AVM_WATCHDOG_ctrl_timer(AVM_WATCHDOG_SET_TIMER, handle); /*--- AVM_WATCHDOG_check_all_triggered(); ---*/ ar7wdt_hw_trigger(); return; } if(handle < 1 || handle > MAX_WDT_APPLS) { DBG(KERN_ERR "AVM_WATCHDOG_timer_handler(hdl=%u): invalid handle\n", handle); return; } handle--; if((ar7wdt_data.mask & (1 << handle)) == 0) { DBG(KERN_ERR "AVM_WATCHDOG_timer_handler(hdl=%u): invalid handle\n", handle + 1); return; } if(ar7wdt_data.states & (1 << handle)) { DBG(KERN_INFO "AVM_WATCHDOG_timer_handler(hdl=%u): timer triggered twice (reboot)\n", handle + 1); AVM_WATCHDOG_reboot(handle + 1); return; } /*--- AVM_WATCHDOG_LOCK_VOID(); ---*/ _AVM_WATCHDOG_ctrl_timer(AVM_WATCHDOG_DEL_TIMER, handle); if(AVM_WATCHDOG_locked) { AVM_WATCHDOG_locked_action |= (1 << handle); return; } AVM_WATCHDOG_timer_handler_action(handle); return; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ EXPORT_SYMBOL(AVM_WATCHDOG_register); EXPORT_SYMBOL(AVM_WATCHDOG_release); EXPORT_SYMBOL(AVM_WATCHDOG_set_timeout); EXPORT_SYMBOL(AVM_WATCHDOG_trigger); EXPORT_SYMBOL(AVM_WATCHDOG_read); EXPORT_SYMBOL(AVM_WATCHDOG_reboot); EXPORT_SYMBOL(AVM_WATCHDOG_poll); EXPORT_SYMBOL(ar7wdt_no_reboot); #endif /*--- #if defined(CONFIG_AVM_WATCHDOG) ---*/