xref: /openbmc/linux/net/rxrpc/call_state.c (revision 9d35d880)
10b9bb322SDavid Howells // SPDX-License-Identifier: GPL-2.0-or-later
20b9bb322SDavid Howells /* Call state changing functions.
30b9bb322SDavid Howells  *
40b9bb322SDavid Howells  * Copyright (C) 2022 Red Hat, Inc. All Rights Reserved.
50b9bb322SDavid Howells  * Written by David Howells (dhowells@redhat.com)
60b9bb322SDavid Howells  */
70b9bb322SDavid Howells 
80b9bb322SDavid Howells #include "ar-internal.h"
90b9bb322SDavid Howells 
100b9bb322SDavid Howells /*
110b9bb322SDavid Howells  * Transition a call to the complete state.
120b9bb322SDavid Howells  */
rxrpc_set_call_completion(struct rxrpc_call * call,enum rxrpc_call_completion compl,u32 abort_code,int error)130b9bb322SDavid Howells bool rxrpc_set_call_completion(struct rxrpc_call *call,
140b9bb322SDavid Howells 				 enum rxrpc_call_completion compl,
150b9bb322SDavid Howells 				 u32 abort_code,
160b9bb322SDavid Howells 				 int error)
170b9bb322SDavid Howells {
1896b4059fSDavid Howells 	if (__rxrpc_call_state(call) == RXRPC_CALL_COMPLETE)
1996b4059fSDavid Howells 		return false;
200b9bb322SDavid Howells 
2196b4059fSDavid Howells 	call->abort_code = abort_code;
2296b4059fSDavid Howells 	call->error = error;
2396b4059fSDavid Howells 	call->completion = compl;
2496b4059fSDavid Howells 	/* Allow reader of completion state to operate locklessly */
2596b4059fSDavid Howells 	rxrpc_set_call_state(call, RXRPC_CALL_COMPLETE);
2696b4059fSDavid Howells 	trace_rxrpc_call_complete(call);
2796b4059fSDavid Howells 	wake_up(&call->waitq);
2896b4059fSDavid Howells 	rxrpc_notify_socket(call);
2996b4059fSDavid Howells 	return true;
300b9bb322SDavid Howells }
310b9bb322SDavid Howells 
320b9bb322SDavid Howells /*
330b9bb322SDavid Howells  * Record that a call successfully completed.
340b9bb322SDavid Howells  */
rxrpc_call_completed(struct rxrpc_call * call)350b9bb322SDavid Howells bool rxrpc_call_completed(struct rxrpc_call *call)
360b9bb322SDavid Howells {
3796b4059fSDavid Howells 	return rxrpc_set_call_completion(call, RXRPC_CALL_SUCCEEDED, 0, 0);
380b9bb322SDavid Howells }
390b9bb322SDavid Howells 
400b9bb322SDavid Howells /*
410b9bb322SDavid Howells  * Record that a call is locally aborted.
420b9bb322SDavid Howells  */
rxrpc_abort_call(struct rxrpc_call * call,rxrpc_seq_t seq,u32 abort_code,int error,enum rxrpc_abort_reason why)4396b4059fSDavid Howells bool rxrpc_abort_call(struct rxrpc_call *call, rxrpc_seq_t seq,
440b9bb322SDavid Howells 		      u32 abort_code, int error, enum rxrpc_abort_reason why)
450b9bb322SDavid Howells {
460b9bb322SDavid Howells 	trace_rxrpc_abort(call->debug_id, why, call->cid, call->call_id, seq,
470b9bb322SDavid Howells 			  abort_code, error);
4896b4059fSDavid Howells 	if (!rxrpc_set_call_completion(call, RXRPC_CALL_LOCALLY_ABORTED,
4996b4059fSDavid Howells 				       abort_code, error))
5096b4059fSDavid Howells 		return false;
5196b4059fSDavid Howells 	if (test_bit(RXRPC_CALL_EXPOSED, &call->flags))
5296b4059fSDavid Howells 		rxrpc_send_abort_packet(call);
5396b4059fSDavid Howells 	return true;
540b9bb322SDavid Howells }
550b9bb322SDavid Howells 
5696b4059fSDavid Howells /*
5796b4059fSDavid Howells  * Record that a call errored out before even getting off the ground, thereby
5896b4059fSDavid Howells  * setting the state to allow it to be destroyed.
5996b4059fSDavid Howells  */
rxrpc_prefail_call(struct rxrpc_call * call,enum rxrpc_call_completion compl,int error)6096b4059fSDavid Howells void rxrpc_prefail_call(struct rxrpc_call *call, enum rxrpc_call_completion compl,
6196b4059fSDavid Howells 			int error)
620b9bb322SDavid Howells {
6396b4059fSDavid Howells 	call->abort_code	= RX_CALL_DEAD;
6496b4059fSDavid Howells 	call->error		= error;
6596b4059fSDavid Howells 	call->completion	= compl;
6696b4059fSDavid Howells 	call->_state		= RXRPC_CALL_COMPLETE;
6796b4059fSDavid Howells 	trace_rxrpc_call_complete(call);
68*9d35d880SDavid Howells 	WARN_ON_ONCE(__test_and_set_bit(RXRPC_CALL_RELEASED, &call->flags));
690b9bb322SDavid Howells }
70