Re: linux2.6.19.2-> mpc8xx_wdt.c: timeout extended to reach several seconds... but I have a problem

2007-11-21 Thread Jochen Friedrich
Hi Antonio,

> I added a kernel timer (triggering every 500 ms) to reset the watchdog
> of mpc8xx. This timer starts when the driver is opened. The timer is
> rearmed till a counter reaches a zero value. A process can use the write
> method of the driver to set the counter to a preferred value. If the
> application misses to set the counter, it will decrease to zero and then
> the board will restart.

You might want to have a look at this patch:

http://patchwork.ozlabs.org/linuxppc-embedded/patch?id=14682

Please make sure to call pq_wdt_init() as early as possible to avoid a
reset during the initial log buffer flush to the serial console.

Thanks,
Jochen
___
Linuxppc-embedded mailing list
Linuxppc-embedded@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-embedded


linux2.6.19.2-> mpc8xx_wdt.c: timeout extended to reach several seconds... but I have a problem

2007-11-20 Thread DI BACCO ANTONIO - technolabs

Till yesterday I thought I was able to code a simple driver but now I'm facing 
a problem that is puzzling me.

I added a kernel timer (triggering every 500 ms) to reset the watchdog of 
mpc8xx. This timer starts when the driver is opened. The timer is rearmed till 
a counter reaches a zero value. A process can use the write method of the 
driver to set the counter to a preferred value. If the application misses to 
set the counter, it will decrease to zero and then the board will restart.

Unfortunately as soon as my application "calls" the write method the kernel 
freezes. If the watchdog is enabled the board restarts otherwise the kernel 
remains blocked forever without any indication. Even if I empty the write 
method leaving only the get_user the board freezes. Below you can find the 
code, if anyone has an hint I would really appreciate his advice:

___
/*
 * mpc8xx_wdt.c - MPC8xx watchdog userspace interface
 *
 * Author: Florian Schirmer <[EMAIL PROTECTED]>
 *
 * 2002 (c) Florian Schirmer <[EMAIL PROTECTED]> This file is licensed under
 * the terms of the GNU General Public License version 2. This program
 * is licensed "as is" without any warranty of any kind, whether express
 * or implied.
 */

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define KTIMER_TIMEOUT  (HZ/2)

static struct timer_list wd_timer;  /* structure for timer administration   
*/
static unsigned long mpc8xx_wdt_dummy;
static int timer_count = 600;
static unsigned long wdt_opened;
static int wdt_status;
static spinlock_t counter_spinlock;

static void mpc8xx_wdt_handler_disable(void)
{
volatile ushort __iomem *piscr;
piscr = (ushort *)&((immap_t*)IMAP_ADDR)->im_sit.sit_piscr;

if (!m8xx_has_internal_rtc)
m8xx_wdt_stop_timer();
else
out_be16(piscr, in_be16(piscr) & ~(PISCR_PIE | PISCR_PTE));

printk(KERN_NOTICE "mpc8xx_wdt: keep-alive handler deactivated\n");
}

static void mpc8xx_wdt_handler_enable(void)
{
volatile ushort __iomem *piscr;
piscr = (ushort *)&((immap_t*)IMAP_ADDR)->im_sit.sit_piscr;

if (!m8xx_has_internal_rtc)
m8xx_wdt_install_timer();
else
out_be16(piscr, in_be16(piscr) | PISCR_PIE | PISCR_PTE);

printk(KERN_NOTICE "mpc8xx_wdt: keep-alive handler activated\n");
}



static int mpc8xx_wdt_open(struct inode *inode, struct file *file)
{
if (test_and_set_bit(0, &wdt_opened))
return -EBUSY;

m8xx_wdt_reset();

wd_timer.expires = jiffies + KTIMER_TIMEOUT;   
add_timer (&wd_timer);  /* ...re-activate timer */ 

mpc8xx_wdt_handler_disable();

return 0;
}

static int mpc8xx_wdt_release(struct inode *inode, struct file *file)
{
m8xx_wdt_reset();

#if !defined(CONFIG_WATCHDOG_NOWAYOUT)
mpc8xx_wdt_handler_enable();
#endif

clear_bit(0, &wdt_opened);

return 0;
}

static void mpc8xx_wdt_ktimer_handler(unsigned long data)
{
int counter;

spin_lock(&counter_spinlock);
counter = timer_count--;
spin_unlock(&counter_spinlock);


printk("Counter %d\n", counter);

if (counter > 0)
{
  wd_timer.expires = jiffies + KTIMER_TIMEOUT;   
  add_timer (&wd_timer);/* ...re-activate timer */ 
  m8xx_wdt_reset();
}
else
{
  printk(KERN_NOTICE "mpc8xx_wdt: Watchdog expired ... restarting\n");
}
}


static ssize_t mpc8xx_wdt_write(struct file *file, const char *data, size_t 
len, loff_t * ppos)
{
unsigned long flags;
int new_count;


if (len != sizeof(new_count)) 
{
return -EINVAL;
}

/* copy count value into kernel space */
get_user(new_count, (int *) data);
printk("new_count %d\n", new_count);

/* Removing the following three lines doesn't prevent 
   the kernel freeze */
spin_lock_irqsave(&counter_spinlock, flags);
timer_count = (HZ*new_count)/KTIMER_TIMEOUT;
spin_unlock_irqrestore(&counter_spinlock, flags);

return (sizeof(new_count));
}

static int mpc8xx_wdt_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
int timeout;
static struct watchdog_info info = {
.options = WDIOF_KEEPALIVEPING,
.firmware_version = 0,
.identity = "MPC8xx watchdog",
};

switch (cmd) {
case WDIOC_GETSUPPORT:
if (copy_to_user((void *)arg, &info, sizeof(info)))
return -EFAULT;
break;

case WDIOC_GETSTATUS:
case WDIOC_GETBOOTSTATUS:
if (put_user(wdt_status, (int *)arg))
return -EFAULT;
wdt_status &