2005-04-17 02:20:36 +04:00
/*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA .
*
* Copyright ( C ) IBM Corporation , 2004
*
2007-07-17 15:03:58 +04:00
* Author : Max Asb <EFBFBD> ck < amax @ us . ibm . com >
2005-04-17 02:20:36 +04:00
*
*/
# 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 = {
2007-07-17 15:03:58 +04:00
. type = sp_read ,
2005-04-17 02:20:36 +04:00
. command_size = 3 ,
. data_size = 0 ,
2007-07-17 15:03:58 +04:00
. status = 0
2005-04-17 02:20:36 +04:00
} ,
. 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 ;
2005-06-22 04:16:36 +04:00
cmd = ibmasm_new_command ( sp , sizeof rhb_dot_cmd ) ;
2005-04-17 02:20:36 +04:00
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 + + ;
2007-07-17 15:03:58 +04:00
wait_event_interruptible_timeout ( rhb - > wait ,
2005-04-17 02:20:36 +04:00
rhb - > stopped ,
2007-07-17 15:03:58 +04:00
REVERSE_HEARTBEAT_TIMEOUT * HZ ) ;
2005-04-17 02:20:36 +04:00
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 ) ;
}