1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* Call state changing functions.
3  *
4  * Copyright (C) 2022 Red Hat, Inc. All Rights Reserved.
5  * Written by David Howells (dhowells@redhat.com)
6  */
7 
8 #include "ar-internal.h"
9 
10 /*
11  * Transition a call to the complete state.
12  */
rxrpc_set_call_completion(struct rxrpc_call * call,enum rxrpc_call_completion compl,u32 abort_code,int error)13 bool rxrpc_set_call_completion(struct rxrpc_call *call,
14 				 enum rxrpc_call_completion compl,
15 				 u32 abort_code,
16 				 int error)
17 {
18 	if (__rxrpc_call_state(call) == RXRPC_CALL_COMPLETE)
19 		return false;
20 
21 	call->abort_code = abort_code;
22 	call->error = error;
23 	call->completion = compl;
24 	/* Allow reader of completion state to operate locklessly */
25 	rxrpc_set_call_state(call, RXRPC_CALL_COMPLETE);
26 	trace_rxrpc_call_complete(call);
27 	wake_up(&call->waitq);
28 	rxrpc_notify_socket(call);
29 	return true;
30 }
31 
32 /*
33  * Record that a call successfully completed.
34  */
rxrpc_call_completed(struct rxrpc_call * call)35 bool rxrpc_call_completed(struct rxrpc_call *call)
36 {
37 	return rxrpc_set_call_completion(call, RXRPC_CALL_SUCCEEDED, 0, 0);
38 }
39 
40 /*
41  * Record that a call is locally aborted.
42  */
rxrpc_abort_call(struct rxrpc_call * call,rxrpc_seq_t seq,u32 abort_code,int error,enum rxrpc_abort_reason why)43 bool rxrpc_abort_call(struct rxrpc_call *call, rxrpc_seq_t seq,
44 		      u32 abort_code, int error, enum rxrpc_abort_reason why)
45 {
46 	trace_rxrpc_abort(call->debug_id, why, call->cid, call->call_id, seq,
47 			  abort_code, error);
48 	if (!rxrpc_set_call_completion(call, RXRPC_CALL_LOCALLY_ABORTED,
49 				       abort_code, error))
50 		return false;
51 	if (test_bit(RXRPC_CALL_EXPOSED, &call->flags))
52 		rxrpc_send_abort_packet(call);
53 	return true;
54 }
55 
56 /*
57  * Record that a call errored out before even getting off the ground, thereby
58  * setting the state to allow it to be destroyed.
59  */
rxrpc_prefail_call(struct rxrpc_call * call,enum rxrpc_call_completion compl,int error)60 void rxrpc_prefail_call(struct rxrpc_call *call, enum rxrpc_call_completion compl,
61 			int error)
62 {
63 	call->abort_code	= RX_CALL_DEAD;
64 	call->error		= error;
65 	call->completion	= compl;
66 	call->_state		= RXRPC_CALL_COMPLETE;
67 	trace_rxrpc_call_complete(call);
68 	WARN_ON_ONCE(__test_and_set_bit(RXRPC_CALL_RELEASED, &call->flags));
69 }
70