Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 
0003 /*
0004  *
0005  * Copyright (C) IBM Corporation, 2004
0006  *
0007  * Author: Max Asböck <amax@us.ibm.com>
0008  */
0009 
0010 #include <linux/sched/signal.h>
0011 #include "ibmasm.h"
0012 #include "dot_command.h"
0013 
0014 /*
0015  * Reverse Heartbeat, i.e. heartbeats sent from the driver to the
0016  * service processor.
0017  * These heartbeats are initiated by user level programs.
0018  */
0019 
0020 /* the reverse heartbeat dot command */
0021 #pragma pack(1)
0022 static struct {
0023     struct dot_command_header   header;
0024     unsigned char           command[3];
0025 } rhb_dot_cmd = {
0026     .header = {
0027         .type =     sp_read,
0028         .command_size = 3,
0029         .data_size =    0,
0030         .status =   0
0031     },
0032     .command = { 4, 3, 6 }
0033 };
0034 #pragma pack()
0035 
0036 void ibmasm_init_reverse_heartbeat(struct service_processor *sp, struct reverse_heartbeat *rhb)
0037 {
0038     init_waitqueue_head(&rhb->wait);
0039     rhb->stopped = 0;
0040 }
0041 
0042 /*
0043  * start_reverse_heartbeat
0044  * Loop forever, sending a reverse heartbeat dot command to the service
0045  * processor, then sleeping. The loop comes to an end if the service
0046  * processor fails to respond 3 times or we were interrupted.
0047  */
0048 int ibmasm_start_reverse_heartbeat(struct service_processor *sp, struct reverse_heartbeat *rhb)
0049 {
0050     struct command *cmd;
0051     int times_failed = 0;
0052     int result = 1;
0053 
0054     cmd = ibmasm_new_command(sp, sizeof rhb_dot_cmd);
0055     if (!cmd)
0056         return -ENOMEM;
0057 
0058     while (times_failed < 3) {
0059         memcpy(cmd->buffer, (void *)&rhb_dot_cmd, sizeof rhb_dot_cmd);
0060         cmd->status = IBMASM_CMD_PENDING;
0061         ibmasm_exec_command(sp, cmd);
0062         ibmasm_wait_for_response(cmd, IBMASM_CMD_TIMEOUT_NORMAL);
0063 
0064         if (cmd->status != IBMASM_CMD_COMPLETE)
0065             times_failed++;
0066 
0067         wait_event_interruptible_timeout(rhb->wait,
0068             rhb->stopped,
0069             REVERSE_HEARTBEAT_TIMEOUT * HZ);
0070 
0071         if (signal_pending(current) || rhb->stopped) {
0072             result = -EINTR;
0073             break;
0074         }
0075     }
0076     command_put(cmd);
0077     rhb->stopped = 0;
0078 
0079     return result;
0080 }
0081 
0082 void ibmasm_stop_reverse_heartbeat(struct reverse_heartbeat *rhb)
0083 {
0084     rhb->stopped = 1;
0085     wake_up_interruptible(&rhb->wait);
0086 }