3 * IBM ASM Service Processor Device Driver
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 * Copyright (C) IBM Corporation, 2004
21 * Author: Max Asböck <amax@us.ibm.com>
25 #include <linux/notifier.h>
27 #include "dot_command.h"
30 static int suspend_heartbeats
= 0;
33 * Once the driver indicates to the service processor that it is running
34 * - see send_os_state() - the service processor sends periodic heartbeats
35 * to the driver. The driver must respond to the heartbeats or else the OS
37 * In the case of a panic the interrupt handler continues to work and thus
38 * continues to respond to heartbeats, making the service processor believe
39 * the OS is still running and thus preventing a reboot.
40 * To prevent this from happening a callback is added the panic_notifier_list.
41 * Before responding to a heartbeat the driver checks if a panic has happened,
42 * if yes it suspends heartbeat, causing the service processor to reboot as
45 static int panic_happened(struct notifier_block
*n
, unsigned long val
, void *v
)
47 suspend_heartbeats
= 1;
51 static struct notifier_block panic_notifier
= { panic_happened
, NULL
, 1 };
53 void ibmasm_register_panic_notifier(void)
55 atomic_notifier_chain_register(&panic_notifier_list
, &panic_notifier
);
58 void ibmasm_unregister_panic_notifier(void)
60 atomic_notifier_chain_unregister(&panic_notifier_list
,
65 int ibmasm_heartbeat_init(struct service_processor
*sp
)
67 sp
->heartbeat
= ibmasm_new_command(sp
, HEARTBEAT_BUFFER_SIZE
);
68 if (sp
->heartbeat
== NULL
)
74 void ibmasm_heartbeat_exit(struct service_processor
*sp
)
78 dbg("%s:%d at %s\n", __FUNCTION__
, __LINE__
, get_timestamp(tsbuf
));
79 ibmasm_wait_for_response(sp
->heartbeat
, IBMASM_CMD_TIMEOUT_NORMAL
);
80 dbg("%s:%d at %s\n", __FUNCTION__
, __LINE__
, get_timestamp(tsbuf
));
81 suspend_heartbeats
= 1;
82 command_put(sp
->heartbeat
);
85 void ibmasm_receive_heartbeat(struct service_processor
*sp
, void *message
, size_t size
)
87 struct command
*cmd
= sp
->heartbeat
;
88 struct dot_command_header
*header
= (struct dot_command_header
*)cmd
->buffer
;
91 dbg("%s:%d at %s\n", __FUNCTION__
, __LINE__
, get_timestamp(tsbuf
));
92 if (suspend_heartbeats
)
95 /* return the received dot command to sender */
96 cmd
->status
= IBMASM_CMD_PENDING
;
97 size
= min(size
, cmd
->buffer_size
);
98 memcpy_fromio(cmd
->buffer
, message
, size
);
99 header
->type
= sp_write
;
100 ibmasm_exec_command(sp
, cmd
);