/*
* ipmi_watchdog.c
*
* A watchdog timer based upon the IPMI interface.
*
* Author: MontaVista Software, Inc.
* Corey Minyard <minyard@mvista.com>
* source@mvista.com
*
* Copyright 2002 MontaVista Software Inc.
*
* 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* 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.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/ipmi.h>
#include <linux/ipmi_smi.h>
#include <linux/mutex.h>
#include <linux/watchdog.h>
#include <linux/miscdevice.h>
#include <linux/init.h>
#include <linux/completion.h>
#include <linux/kdebug.h>
#include <linux/rwsem.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
#include <linux/notifier.h>
#include <linux/nmi.h>
#include <linux/reboot.h>
#include <linux/wait.h>
#include <linux/poll.h>
#include <linux/string.h>
#include <linux/ctype.h>
#include <linux/delay.h>
#include <linux/atomic.h>
#ifdef CONFIG_X86
/*
* This is ugly, but I've determined that x86 is the only architecture
* that can reasonably support the IPMI NMI watchdog timeout at this
* time. If another architecture adds this capability somehow, it
* will have to be a somewhat different mechanism and I have no idea
* how it will work. So in the unlikely event that another
* architecture supports this, we can figure out a good generic
* mechanism for it at that time.
*/
#include <asm/kdebug.h>
#include <asm/nmi.h>
#define HAVE_DIE_NMI
#endif
#define PFX "IPMI Watchdog: "
/*
* The IPMI command/response information for the watchdog timer.
*/
/* values for byte 1 of the set command, byte 2 of the get response. */
#define WDOG_DONT_LOG (1 << 7)
#define WDOG_DONT_STOP_ON_SET (1 << 6)
#define WDOG_SET_TIMER_USE(byte, use) \
byte = ((byte) & 0xf8) | ((use) & 0x7)
#define WDOG_GET_TIMER_USE(byte) ((byte) & 0x7)
#define WDOG_TIMER_USE_BIOS_FRB2 1
#define WDOG_TIMER_USE_BIOS_POST 2
#define WDOG_TIMER_USE_OS_LOAD 3
#define WDOG_TIMER_USE_SMS_OS 4
#define WDOG_TIMER_USE_OEM 5
/* values for byte 2 of the set command, byte 3 of the get response. */
#define WDOG_SET_PRETIMEOUT_ACT(byte, use) \
byte = ((byte) & 0x8f) | (((use) & 0x7) << 4)
#define WDOG_GET_PRETIMEOUT_ACT(byte) (((byte) >> 4) & 0x7)
#define WDOG_PRETIMEOUT_NONE 0
#define WDOG_PRETIMEOUT_SMI 1
#define WDOG_PRETIMEOUT_NMI 2
#define WDOG_PRETIMEOUT_MSG_INT 3
/* Operations that can be performed on a pretimout. */
#define WDOG_PREOP_NONE 0
#define WDOG_PREOP_PANIC 1
/* Cause data to be available to read. Doesn't work in NMI mode. */
#define WDOG_PREOP_GIVE_DATA 2
/* Actions to perform on a full timeout. */
#define WDOG_SET_TIMEOUT_ACT(byte, use) \
byte = ((byte) & 0xf8) | ((use) & 0x7)
#define WDOG_GET_TIMEOUT_ACT(byte) ((byte) & 0x7)
#define WDOG_TIMEOUT_NONE 0
#define WDOG_TIMEOUT_RESET 1
#define WDOG_TIMEOUT_POWER_DOWN 2
#define WDOG_TIMEOUT_POWER_CYCLE 3
/*
* Byte 3 of the get command, byte 4 of the get response is the
* pre-timeout in seconds.
*/
/* Bits for setting byte 4 of the set command, byte 5 of the get response. */
#define WDOG_EXPIRE_CLEAR_BIOS_FRB2 (1 << 1)
#define WDOG_EXPIRE_CLEAR_BIOS_POST (1 << 2)
#define WDOG_EXPIRE_CLEAR_OS_LOAD (1 << 3)
#define WDOG_EXPIRE_CLEAR_SMS_OS (1 << 4)