/*********************************************************************** F* Function: int wdt_mpc8xx_unregister_mon_chain(unsigned int chainid) P*A*Z* * P* Parameters: unsigned int chainid P* - The id of the chain to unregister P* P* Returnvalue: int P* - 0 The chain was unregistered successfully P* -EINVAL The chainid is unknown * Z* Intention: When the watchdog functionality is no longer needed, Z* chains can be unregistered through this call. Z* The function is called through the ioctl() mechanism Z* or directly from other kernel proper, as it is exported. * D* Design: [email protected] C* Coding: [email protected] V* Verification: [email protected] ***********************************************************************/ int wdt_mpc8xx_unregister_mon_chain(unsigned int chainid) { monitored_chain_t *entry; if ((entry=find_mon_chain_by_chainid(chainid))==NULL) return(-EINVAL); debugk("%s: WDT8xx unregistering monitor for id %d\n", __FUNCTION__, entry->chainid); spin_lock(&mon_lock); list_del(&entry->list); kfree(entry); spin_unlock(&mon_lock); return(0); }
/*********************************************************************** F* Function: int wd_reset_mon_chain(int chainid) P*A*Z* * P* Parameters: int chainid P* - The id of the chain to reset P* P* Returnvalue: int P* - 0 The chain was reset suiccessfully P* <0 Errorcondition, which can be P* -EINVAL The supplied id is unknown. * Z* Intention: This function resets a chain to its initial state. Z* The function is called through the ioctl() mechanism Z* to reset or trigger a chain or directly from other Z* kernel proper, as it is exported. * D* Design: [email protected] C* Coding: [email protected] V* Verification: [email protected] ***********************************************************************/ int wd_reset_mon_chain(int chainid) { monitored_chain_t *entry; int result = 0; debugk("%s: WD monitor reset for id %d\n", __FUNCTION__, chainid); spin_lock(&mon_lock); if ((entry = find_mon_chain_by_chainid(chainid)) == NULL) { result = -EINVAL; goto out; } entry->escalation = 0; entry->expires = jiffies + HZ * entry->timer_count[0]; list_del(&entry->list); insert_mon_chain(entry); out: spin_unlock(&mon_lock); return result; }
/*********************************************************************** F* Function: static int register_mon_chain(wdt_mpc8xx_param_t *param, F* int userproc) P*A*Z* * P* Parameters: wdt_mpc8xx_param_t *param P* - The parameters for the chain to be registered. P* Unused stages should be cleared with 0's. P* int userproc P* - Flag whether we are called from user or kernel space P* P* Returnvalue: int P* - 0 success P* -EINVAL invalid parameters P* -ENOMEM out of memory * Z* Intention: This is the main interface to register a watchdog chain Z* either from userspace throught ioctl() or from kernel Z* space through the wrapper function Z* wdt_mpc8x_register_mon_chain(). Z* Re-registering an existing chain is explicitely ok, as Z* a restarted process has to go through this. This Z* effectively resets the corresponding chain. Z* For a detailed description of the parameters, see the Z* wdt_mpc8xx(4) manpage. * D* Design: [email protected] C* Coding: [email protected] V* Verification: [email protected] ***********************************************************************/ static int register_mon_chain(wdt_mpc8xx_param_t *param, int userproc) { monitored_chain_t *entry; int result=0, i; /* Before kmallocing storage we first check the parameters */ for (i=0; (i<3)&&(param->timer_count[i]); i++) if ((param->action[i]<WDT_MPC8XX_ACTION_SIGNAL)|| (param->action[i]>WDT_MPC8XX_ACTION_RESET)) return(-EINVAL); debugk("%s: registering WDT8xx monitor\n", __FUNCTION__); spin_lock(&mon_lock); if ((entry=find_mon_chain_by_chainid(param->chainid))==NULL) { /* New chain-id so allocate list entry */ entry=(monitored_chain_t *)kmalloc(sizeof(monitored_chain_t), GFP_KERNEL); if (entry==NULL) { result=-ENOMEM; goto out; } /* Copy request data to internal format */ if (userproc) entry->pid=current->pid; else entry->pid=0; entry->chainid=param->chainid; entry->signal=param->signal; for (i=0; i<2 ; i++) { if (entry->action[i]!=0) { entry->timer_count[i]=param->timer_count[i]; entry->action[i]=param->action[i]; } else { /* Fill with stop entries */ entry->timer_count[i]=2; entry->action[i]=WDT_MPC8XX_ACTION_RESET; } } /* This is a final stop entry */ entry->timer_count[3]=2; entry->action[3]=WDT_MPC8XX_ACTION_RESET; /* Initialize internal data */ entry->escalation=0; entry->expires=jiffies + HZ * entry->timer_count[0]; insert_mon_chain(entry); mon_chains++; } else { /* Re-registering of active monitor */ entry->pid=current->pid; entry->escalation=0; entry->expires=jiffies + HZ * entry->timer_count[0]; entry->escalation=0; list_del(&entry->list); insert_mon_chain(entry); } out: spin_unlock(&mon_lock); return(result); }