r_heartbeat.c 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. *
  4. * Copyright (C) IBM Corporation, 2004
  5. *
  6. * Author: Max Asböck <amax@us.ibm.com>
  7. */
  8. #include <linux/sched/signal.h>
  9. #include "ibmasm.h"
  10. #include "dot_command.h"
  11. /*
  12. * Reverse Heartbeat, i.e. heartbeats sent from the driver to the
  13. * service processor.
  14. * These heartbeats are initiated by user level programs.
  15. */
  16. /* the reverse heartbeat dot command */
  17. #pragma pack(1)
  18. static struct {
  19. struct dot_command_header header;
  20. unsigned char command[3];
  21. } rhb_dot_cmd = {
  22. .header = {
  23. .type = sp_read,
  24. .command_size = 3,
  25. .data_size = 0,
  26. .status = 0
  27. },
  28. .command = { 4, 3, 6 }
  29. };
  30. #pragma pack()
  31. void ibmasm_init_reverse_heartbeat(struct service_processor *sp, struct reverse_heartbeat *rhb)
  32. {
  33. init_waitqueue_head(&rhb->wait);
  34. rhb->stopped = 0;
  35. }
  36. /*
  37. * start_reverse_heartbeat
  38. * Loop forever, sending a reverse heartbeat dot command to the service
  39. * processor, then sleeping. The loop comes to an end if the service
  40. * processor fails to respond 3 times or we were interrupted.
  41. */
  42. int ibmasm_start_reverse_heartbeat(struct service_processor *sp, struct reverse_heartbeat *rhb)
  43. {
  44. struct command *cmd;
  45. int times_failed = 0;
  46. int result = 1;
  47. cmd = ibmasm_new_command(sp, sizeof rhb_dot_cmd);
  48. if (!cmd)
  49. return -ENOMEM;
  50. while (times_failed < 3) {
  51. memcpy(cmd->buffer, (void *)&rhb_dot_cmd, sizeof rhb_dot_cmd);
  52. cmd->status = IBMASM_CMD_PENDING;
  53. ibmasm_exec_command(sp, cmd);
  54. ibmasm_wait_for_response(cmd, IBMASM_CMD_TIMEOUT_NORMAL);
  55. if (cmd->status != IBMASM_CMD_COMPLETE)
  56. times_failed++;
  57. wait_event_interruptible_timeout(rhb->wait,
  58. rhb->stopped,
  59. REVERSE_HEARTBEAT_TIMEOUT * HZ);
  60. if (signal_pending(current) || rhb->stopped) {
  61. result = -EINTR;
  62. break;
  63. }
  64. }
  65. command_put(cmd);
  66. rhb->stopped = 0;
  67. return result;
  68. }
  69. void ibmasm_stop_reverse_heartbeat(struct reverse_heartbeat *rhb)
  70. {
  71. rhb->stopped = 1;
  72. wake_up_interruptible(&rhb->wait);
  73. }