1 // SPDX-License-Identifier: GPL-2.0-or-later
4 * IBM ASM Service Processor Device Driver
6 * Copyright (C) IBM Corporation, 2004
8 * Author: Max Asböck <amax@us.ibm.com>
11 #include <linux/notifier.h>
13 #include "dot_command.h"
16 static int suspend_heartbeats
= 0;
19 * Once the driver indicates to the service processor that it is running
20 * - see send_os_state() - the service processor sends periodic heartbeats
21 * to the driver. The driver must respond to the heartbeats or else the OS
23 * In the case of a panic the interrupt handler continues to work and thus
24 * continues to respond to heartbeats, making the service processor believe
25 * the OS is still running and thus preventing a reboot.
26 * To prevent this from happening a callback is added the panic_notifier_list.
27 * Before responding to a heartbeat the driver checks if a panic has happened,
28 * if yes it suspends heartbeat, causing the service processor to reboot as
31 static int panic_happened(struct notifier_block
*n
, unsigned long val
, void *v
)
33 suspend_heartbeats
= 1;
37 static struct notifier_block panic_notifier
= { panic_happened
, NULL
, 1 };
39 void ibmasm_register_panic_notifier(void)
41 atomic_notifier_chain_register(&panic_notifier_list
, &panic_notifier
);
44 void ibmasm_unregister_panic_notifier(void)
46 atomic_notifier_chain_unregister(&panic_notifier_list
,
51 int ibmasm_heartbeat_init(struct service_processor
*sp
)
53 sp
->heartbeat
= ibmasm_new_command(sp
, HEARTBEAT_BUFFER_SIZE
);
54 if (sp
->heartbeat
== NULL
)
60 void ibmasm_heartbeat_exit(struct service_processor
*sp
)
64 dbg("%s:%d at %s\n", __func__
, __LINE__
, get_timestamp(tsbuf
));
65 ibmasm_wait_for_response(sp
->heartbeat
, IBMASM_CMD_TIMEOUT_NORMAL
);
66 dbg("%s:%d at %s\n", __func__
, __LINE__
, get_timestamp(tsbuf
));
67 suspend_heartbeats
= 1;
68 command_put(sp
->heartbeat
);
71 void ibmasm_receive_heartbeat(struct service_processor
*sp
, void *message
, size_t size
)
73 struct command
*cmd
= sp
->heartbeat
;
74 struct dot_command_header
*header
= (struct dot_command_header
*)cmd
->buffer
;
77 dbg("%s:%d at %s\n", __func__
, __LINE__
, get_timestamp(tsbuf
));
78 if (suspend_heartbeats
)
81 /* return the received dot command to sender */
82 cmd
->status
= IBMASM_CMD_PENDING
;
83 size
= min(size
, cmd
->buffer_size
);
84 memcpy_fromio(cmd
->buffer
, message
, size
);
85 header
->type
= sp_write
;
86 ibmasm_exec_command(sp
, cmd
);