[prev in list] [next in list] [prev in thread] [next in thread] 

List:       busybox
Subject:    Re: [BusyBox] Reset halts but doesn't reboot
From:       Andrew McKay <amckay () iders ! ca>
Date:       2005-04-22 21:30:59
Message-ID: 42696D13.8040208 () iders ! ca
[Download RAW message or body]

Andrew McKay wrote:

> Hi,
> 
> I'm having problems with the "reset" command in BusyBox.  I have tried 
> to figure out the code involved in the reset as much as possible.  It 
> seems that what is happening is that the system call that tells the 
> Linux kernel to reset the board is failing.  The cause seems to be 
> when init sends SIGKILL to all of the running processes, after this 
> command is complete the Kernel does not want to respond to 
> init_reboot(RB_AUTOBOOT);
> 
> [SNIP]
> _______________________________________________
> busybox mailing list
> busybox@mail.busybox.net
> http://codepoet.org/mailman/listinfo/busybox
> 
> 
Hi Guys,

I have found a partial solution to the problem.  I will post it so that 
if anyone else runs into something similar they will have something to 
look for.

I had found that if I removed all of the sleep() calls after the 
SIG_KILL message that the board would reset more frequently (though not 
always).  However this obviously didn't seem the proper way to fix 
things.  The sleeps are necessary so that the SIG_KILL message has time 
to get to all of the processes. 

Code from init.c in BusyBox 0.60 (Worked similarly in BusyBox 1.0):
------------------------------------------------------------------------------------------------------------------- \


static void shutdown_system(void)
{
   sigset_t block_signals;

   /* run everything to be run at "shutdown".  This is done _prior_
    * to killing everything, in case people wish to use scripts to
    * shut things down gracefully... */
   run_actions(SHUTDOWN);

   /* first disable all our signals */
   sigemptyset(&block_signals);
   sigaddset(&block_signals, SIGHUP);
   sigaddset(&block_signals, SIGCHLD);
   sigaddset(&block_signals, SIGUSR1);
   sigaddset(&block_signals, SIGUSR2);
   sigaddset(&block_signals, SIGINT);
   sigaddset(&block_signals, SIGTERM);
   sigaddset(&block_signals, SIGCONT);
   sigaddset(&block_signals, SIGSTOP);
   sigaddset(&block_signals, SIGTSTP);
   sigprocmask(SIG_BLOCK, &block_signals, NULL);

   /* Allow Ctrl-Alt-Del to reboot system. */
   init_reboot(RB_ENABLE_CAD);

   message(CONSOLE|LOG, "\n\rThe system is going down NOW !!\n");
   sync();

   /* Send signals to every process _except_ pid 1 */
   message(CONSOLE|LOG, "\rSending SIGTERM to all processes.\n");
   kill(-1, SIGTERM);
   sleep(1);
   sync();

   message(CONSOLE|LOG, "\rSending SIGKILL to all processes.\n");
   kill(-1, SIGKILL);
   //sleep(1);  //Comment out this sleep to get a reboot

   sync();
   if (kernelVersion > 0 && kernelVersion <= KERNEL_VERSION(2,2,11)) {
       /* bdflush, kupdate not needed for kernels >2.2.11 */
       bdflush(1, 0);
       sync();
   }
}

static void reboot_signal(int sig)
{
   shutdown_system();
   message(CONSOLE|LOG, "\rPlease stand by while rebooting the system.\n");
   sync();

   /* allow time for last message to reach serial console */
   //sleep(2);     //Comment out a sleep to get a reboot

   init_reboot(RB_AUTOBOOT);

   loop_forever();
}
------------------------------------------------------------------------------------------------------------------- \



I decided to debug the kernel a bit further (I am using 2.4.21-RMK1 on a 
Cirrus Logic EP9301).

I used some GPIOs to debug the Linux system call sys_reboot() which is 
found in kernel directory in a file called sys.c.  I drive the lines low 
so that I can light some LEDs on my board.

       case LINUX_REBOOT_CMD_RESTART:
                outl(inl(GPIO_PFDDR) | 0x02, GPIO_PFDDR);
                outl(inl(GPIO_PFDR) & ~0x02, GPIO_PFDR);
                notifier_call_chain(&reboot_notifier_list, SYS_RESTART, 
NULL);
                outl(inl(GPIO_PFDDR) | 0x04, GPIO_PFDDR);
                outl(inl(GPIO_PFDR) & ~0x04, GPIO_PFDR);
                printk(KERN_EMERG "Restarting system.\n");
                outl(inl(GPIO_PFDDR) | 0x08, GPIO_PFDDR);
                outl(inl(GPIO_PFDR) & ~0x08, GPIO_PFDR);
                machine_restart(NULL);
                break;

The code was not executing past the printk(KERN_EMERG "Restarting 
system.\n");  I removed this line, and reboots work like a charm.  For 
some reason the printk is halting the system.  I have not had time to 
figure out why, so for the mean time I am commenting out the printk in 
this system call.

Andrew McKay
Iders Incorporated
_______________________________________________
busybox mailing list
busybox@mail.busybox.net
http://codepoet.org/mailman/listinfo/busybox


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic