2022-10-27 00:16:55 +01:00
// SPDX-License-Identifier: GPL-2.0-or-later
/* Call state changing functions.
*
* Copyright ( C ) 2022 Red Hat , Inc . All Rights Reserved .
* Written by David Howells ( dhowells @ redhat . com )
*/
# include "ar-internal.h"
/*
* Transition a call to the complete state .
*/
bool __rxrpc_set_call_completion ( struct rxrpc_call * call ,
enum rxrpc_call_completion compl ,
u32 abort_code ,
int error )
{
if ( call - > state < RXRPC_CALL_COMPLETE ) {
call - > abort_code = abort_code ;
call - > error = error ;
call - > completion = compl ;
2022-12-19 15:32:32 +00:00
/* Allow reader of completion state to operate locklessly */
smp_store_release ( & call - > state , RXRPC_CALL_COMPLETE ) ;
2022-10-27 00:16:55 +01:00
trace_rxrpc_call_complete ( call ) ;
wake_up ( & call - > waitq ) ;
rxrpc_notify_socket ( call ) ;
return true ;
}
return false ;
}
bool rxrpc_set_call_completion ( struct rxrpc_call * call ,
enum rxrpc_call_completion compl ,
u32 abort_code ,
int error )
{
bool ret = false ;
if ( call - > state < RXRPC_CALL_COMPLETE ) {
write_lock ( & call - > state_lock ) ;
ret = __rxrpc_set_call_completion ( call , compl , abort_code , error ) ;
write_unlock ( & call - > state_lock ) ;
}
return ret ;
}
/*
* Record that a call successfully completed .
*/
bool __rxrpc_call_completed ( struct rxrpc_call * call )
{
return __rxrpc_set_call_completion ( call , RXRPC_CALL_SUCCEEDED , 0 , 0 ) ;
}
bool rxrpc_call_completed ( struct rxrpc_call * call )
{
bool ret = false ;
if ( call - > state < RXRPC_CALL_COMPLETE ) {
write_lock ( & call - > state_lock ) ;
ret = __rxrpc_call_completed ( call ) ;
write_unlock ( & call - > state_lock ) ;
}
return ret ;
}
/*
* Record that a call is locally aborted .
*/
bool __rxrpc_abort_call ( struct rxrpc_call * call , rxrpc_seq_t seq ,
u32 abort_code , int error , enum rxrpc_abort_reason why )
{
trace_rxrpc_abort ( call - > debug_id , why , call - > cid , call - > call_id , seq ,
abort_code , error ) ;
return __rxrpc_set_call_completion ( call , RXRPC_CALL_LOCALLY_ABORTED ,
abort_code , error ) ;
}
bool rxrpc_abort_call ( struct rxrpc_call * call , rxrpc_seq_t seq ,
u32 abort_code , int error , enum rxrpc_abort_reason why )
{
bool ret ;
write_lock ( & call - > state_lock ) ;
ret = __rxrpc_abort_call ( call , seq , abort_code , error , why ) ;
write_unlock ( & call - > state_lock ) ;
if ( ret & & test_bit ( RXRPC_CALL_EXPOSED , & call - > flags ) )
rxrpc_send_abort_packet ( call ) ;
return ret ;
}