1/*2* IBM ASM Service Processor Device Driver3*4* This program is free software; you can redistribute it and/or modify5* it under the terms of the GNU General Public License as published by6* the Free Software Foundation; either version 2 of the License, or7* (at your option) any later version.8*9* This program is distributed in the hope that it will be useful,10* but WITHOUT ANY WARRANTY; without even the implied warranty of11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12* GNU General Public License for more details.13*14* You should have received a copy of the GNU General Public License15* along with this program; if not, write to the Free Software16* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.17*18* Copyright (C) IBM Corporation, 200419*20* Author: Max Asb�ck <[email protected]>21*22*/2324#include <linux/notifier.h>25#include "ibmasm.h"26#include "dot_command.h"27#include "lowlevel.h"2829static int suspend_heartbeats = 0;3031/*32* Once the driver indicates to the service processor that it is running33* - see send_os_state() - the service processor sends periodic heartbeats34* to the driver. The driver must respond to the heartbeats or else the OS35* will be rebooted.36* In the case of a panic the interrupt handler continues to work and thus37* continues to respond to heartbeats, making the service processor believe38* the OS is still running and thus preventing a reboot.39* To prevent this from happening a callback is added the panic_notifier_list.40* Before responding to a heartbeat the driver checks if a panic has happened,41* if yes it suspends heartbeat, causing the service processor to reboot as42* expected.43*/44static int panic_happened(struct notifier_block *n, unsigned long val, void *v)45{46suspend_heartbeats = 1;47return 0;48}4950static struct notifier_block panic_notifier = { panic_happened, NULL, 1 };5152void ibmasm_register_panic_notifier(void)53{54atomic_notifier_chain_register(&panic_notifier_list, &panic_notifier);55}5657void ibmasm_unregister_panic_notifier(void)58{59atomic_notifier_chain_unregister(&panic_notifier_list,60&panic_notifier);61}626364int ibmasm_heartbeat_init(struct service_processor *sp)65{66sp->heartbeat = ibmasm_new_command(sp, HEARTBEAT_BUFFER_SIZE);67if (sp->heartbeat == NULL)68return -ENOMEM;6970return 0;71}7273void ibmasm_heartbeat_exit(struct service_processor *sp)74{75char tsbuf[32];7677dbg("%s:%d at %s\n", __func__, __LINE__, get_timestamp(tsbuf));78ibmasm_wait_for_response(sp->heartbeat, IBMASM_CMD_TIMEOUT_NORMAL);79dbg("%s:%d at %s\n", __func__, __LINE__, get_timestamp(tsbuf));80suspend_heartbeats = 1;81command_put(sp->heartbeat);82}8384void ibmasm_receive_heartbeat(struct service_processor *sp, void *message, size_t size)85{86struct command *cmd = sp->heartbeat;87struct dot_command_header *header = (struct dot_command_header *)cmd->buffer;88char tsbuf[32];8990dbg("%s:%d at %s\n", __func__, __LINE__, get_timestamp(tsbuf));91if (suspend_heartbeats)92return;9394/* return the received dot command to sender */95cmd->status = IBMASM_CMD_PENDING;96size = min(size, cmd->buffer_size);97memcpy_fromio(cmd->buffer, message, size);98header->type = sp_write;99ibmasm_exec_command(sp, cmd);100}101102103