mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
86 lines
1.9 KiB
86 lines
1.9 KiB
// SPDX-License-Identifier: GPL-2.0-or-later |
|
|
|
/* |
|
* |
|
* Copyright (C) IBM Corporation, 2004 |
|
* |
|
* Author: Max Asböck <[email protected]> |
|
*/ |
|
|
|
#include <linux/sched/signal.h> |
|
#include "ibmasm.h" |
|
#include "dot_command.h" |
|
|
|
/* |
|
* Reverse Heartbeat, i.e. heartbeats sent from the driver to the |
|
* service processor. |
|
* These heartbeats are initiated by user level programs. |
|
*/ |
|
|
|
/* the reverse heartbeat dot command */ |
|
#pragma pack(1) |
|
static struct { |
|
struct dot_command_header header; |
|
unsigned char command[3]; |
|
} rhb_dot_cmd = { |
|
.header = { |
|
.type = sp_read, |
|
.command_size = 3, |
|
.data_size = 0, |
|
.status = 0 |
|
}, |
|
.command = { 4, 3, 6 } |
|
}; |
|
#pragma pack() |
|
|
|
void ibmasm_init_reverse_heartbeat(struct service_processor *sp, struct reverse_heartbeat *rhb) |
|
{ |
|
init_waitqueue_head(&rhb->wait); |
|
rhb->stopped = 0; |
|
} |
|
|
|
/* |
|
* start_reverse_heartbeat |
|
* Loop forever, sending a reverse heartbeat dot command to the service |
|
* processor, then sleeping. The loop comes to an end if the service |
|
* processor fails to respond 3 times or we were interrupted. |
|
*/ |
|
int ibmasm_start_reverse_heartbeat(struct service_processor *sp, struct reverse_heartbeat *rhb) |
|
{ |
|
struct command *cmd; |
|
int times_failed = 0; |
|
int result = 1; |
|
|
|
cmd = ibmasm_new_command(sp, sizeof rhb_dot_cmd); |
|
if (!cmd) |
|
return -ENOMEM; |
|
|
|
while (times_failed < 3) { |
|
memcpy(cmd->buffer, (void *)&rhb_dot_cmd, sizeof rhb_dot_cmd); |
|
cmd->status = IBMASM_CMD_PENDING; |
|
ibmasm_exec_command(sp, cmd); |
|
ibmasm_wait_for_response(cmd, IBMASM_CMD_TIMEOUT_NORMAL); |
|
|
|
if (cmd->status != IBMASM_CMD_COMPLETE) |
|
times_failed++; |
|
|
|
wait_event_interruptible_timeout(rhb->wait, |
|
rhb->stopped, |
|
REVERSE_HEARTBEAT_TIMEOUT * HZ); |
|
|
|
if (signal_pending(current) || rhb->stopped) { |
|
result = -EINTR; |
|
break; |
|
} |
|
} |
|
command_put(cmd); |
|
rhb->stopped = 0; |
|
|
|
return result; |
|
} |
|
|
|
void ibmasm_stop_reverse_heartbeat(struct reverse_heartbeat *rhb) |
|
{ |
|
rhb->stopped = 1; |
|
wake_up_interruptible(&rhb->wait); |
|
}
|
|
|