xref: /openbmc/linux/net/rxrpc/call_state.c (revision 0b9bb322)
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  */
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 (call->state < RXRPC_CALL_COMPLETE) {
19 		call->abort_code = abort_code;
20 		call->error = error;
21 		call->completion = compl;
22 		call->state = RXRPC_CALL_COMPLETE;
23 		trace_rxrpc_call_complete(call);
24 		wake_up(&call->waitq);
25 		rxrpc_notify_socket(call);
26 		return true;
27 	}
28 	return false;
29 }
30 
31 bool rxrpc_set_call_completion(struct rxrpc_call *call,
32 			       enum rxrpc_call_completion compl,
33 			       u32 abort_code,
34 			       int error)
35 {
36 	bool ret = false;
37 
38 	if (call->state < RXRPC_CALL_COMPLETE) {
39 		write_lock(&call->state_lock);
40 		ret = __rxrpc_set_call_completion(call, compl, abort_code, error);
41 		write_unlock(&call->state_lock);
42 	}
43 	return ret;
44 }
45 
46 /*
47  * Record that a call successfully completed.
48  */
49 bool __rxrpc_call_completed(struct rxrpc_call *call)
50 {
51 	return __rxrpc_set_call_completion(call, RXRPC_CALL_SUCCEEDED, 0, 0);
52 }
53 
54 bool rxrpc_call_completed(struct rxrpc_call *call)
55 {
56 	bool ret = false;
57 
58 	if (call->state < RXRPC_CALL_COMPLETE) {
59 		write_lock(&call->state_lock);
60 		ret = __rxrpc_call_completed(call);
61 		write_unlock(&call->state_lock);
62 	}
63 	return ret;
64 }
65 
66 /*
67  * Record that a call is locally aborted.
68  */
69 bool __rxrpc_abort_call(struct rxrpc_call *call, rxrpc_seq_t seq,
70 			u32 abort_code, int error, enum rxrpc_abort_reason why)
71 {
72 	trace_rxrpc_abort(call->debug_id, why, call->cid, call->call_id, seq,
73 			  abort_code, error);
74 	return __rxrpc_set_call_completion(call, RXRPC_CALL_LOCALLY_ABORTED,
75 					   abort_code, error);
76 }
77 
78 bool rxrpc_abort_call(struct rxrpc_call *call, rxrpc_seq_t seq,
79 		      u32 abort_code, int error, enum rxrpc_abort_reason why)
80 {
81 	bool ret;
82 
83 	write_lock(&call->state_lock);
84 	ret = __rxrpc_abort_call(call, seq, abort_code, error, why);
85 	write_unlock(&call->state_lock);
86 	if (ret && test_bit(RXRPC_CALL_EXPOSED, &call->flags))
87 		rxrpc_send_abort_packet(call);
88 	return ret;
89 }
90