xref: /openbmc/linux/net/rxrpc/call_state.c (revision 0b9bb322)
1*0b9bb322SDavid Howells // SPDX-License-Identifier: GPL-2.0-or-later
2*0b9bb322SDavid Howells /* Call state changing functions.
3*0b9bb322SDavid Howells  *
4*0b9bb322SDavid Howells  * Copyright (C) 2022 Red Hat, Inc. All Rights Reserved.
5*0b9bb322SDavid Howells  * Written by David Howells (dhowells@redhat.com)
6*0b9bb322SDavid Howells  */
7*0b9bb322SDavid Howells 
8*0b9bb322SDavid Howells #include "ar-internal.h"
9*0b9bb322SDavid Howells 
10*0b9bb322SDavid Howells /*
11*0b9bb322SDavid Howells  * Transition a call to the complete state.
12*0b9bb322SDavid Howells  */
13*0b9bb322SDavid Howells bool __rxrpc_set_call_completion(struct rxrpc_call *call,
14*0b9bb322SDavid Howells 				 enum rxrpc_call_completion compl,
15*0b9bb322SDavid Howells 				 u32 abort_code,
16*0b9bb322SDavid Howells 				 int error)
17*0b9bb322SDavid Howells {
18*0b9bb322SDavid Howells 	if (call->state < RXRPC_CALL_COMPLETE) {
19*0b9bb322SDavid Howells 		call->abort_code = abort_code;
20*0b9bb322SDavid Howells 		call->error = error;
21*0b9bb322SDavid Howells 		call->completion = compl;
22*0b9bb322SDavid Howells 		call->state = RXRPC_CALL_COMPLETE;
23*0b9bb322SDavid Howells 		trace_rxrpc_call_complete(call);
24*0b9bb322SDavid Howells 		wake_up(&call->waitq);
25*0b9bb322SDavid Howells 		rxrpc_notify_socket(call);
26*0b9bb322SDavid Howells 		return true;
27*0b9bb322SDavid Howells 	}
28*0b9bb322SDavid Howells 	return false;
29*0b9bb322SDavid Howells }
30*0b9bb322SDavid Howells 
31*0b9bb322SDavid Howells bool rxrpc_set_call_completion(struct rxrpc_call *call,
32*0b9bb322SDavid Howells 			       enum rxrpc_call_completion compl,
33*0b9bb322SDavid Howells 			       u32 abort_code,
34*0b9bb322SDavid Howells 			       int error)
35*0b9bb322SDavid Howells {
36*0b9bb322SDavid Howells 	bool ret = false;
37*0b9bb322SDavid Howells 
38*0b9bb322SDavid Howells 	if (call->state < RXRPC_CALL_COMPLETE) {
39*0b9bb322SDavid Howells 		write_lock(&call->state_lock);
40*0b9bb322SDavid Howells 		ret = __rxrpc_set_call_completion(call, compl, abort_code, error);
41*0b9bb322SDavid Howells 		write_unlock(&call->state_lock);
42*0b9bb322SDavid Howells 	}
43*0b9bb322SDavid Howells 	return ret;
44*0b9bb322SDavid Howells }
45*0b9bb322SDavid Howells 
46*0b9bb322SDavid Howells /*
47*0b9bb322SDavid Howells  * Record that a call successfully completed.
48*0b9bb322SDavid Howells  */
49*0b9bb322SDavid Howells bool __rxrpc_call_completed(struct rxrpc_call *call)
50*0b9bb322SDavid Howells {
51*0b9bb322SDavid Howells 	return __rxrpc_set_call_completion(call, RXRPC_CALL_SUCCEEDED, 0, 0);
52*0b9bb322SDavid Howells }
53*0b9bb322SDavid Howells 
54*0b9bb322SDavid Howells bool rxrpc_call_completed(struct rxrpc_call *call)
55*0b9bb322SDavid Howells {
56*0b9bb322SDavid Howells 	bool ret = false;
57*0b9bb322SDavid Howells 
58*0b9bb322SDavid Howells 	if (call->state < RXRPC_CALL_COMPLETE) {
59*0b9bb322SDavid Howells 		write_lock(&call->state_lock);
60*0b9bb322SDavid Howells 		ret = __rxrpc_call_completed(call);
61*0b9bb322SDavid Howells 		write_unlock(&call->state_lock);
62*0b9bb322SDavid Howells 	}
63*0b9bb322SDavid Howells 	return ret;
64*0b9bb322SDavid Howells }
65*0b9bb322SDavid Howells 
66*0b9bb322SDavid Howells /*
67*0b9bb322SDavid Howells  * Record that a call is locally aborted.
68*0b9bb322SDavid Howells  */
69*0b9bb322SDavid Howells bool __rxrpc_abort_call(struct rxrpc_call *call, rxrpc_seq_t seq,
70*0b9bb322SDavid Howells 			u32 abort_code, int error, enum rxrpc_abort_reason why)
71*0b9bb322SDavid Howells {
72*0b9bb322SDavid Howells 	trace_rxrpc_abort(call->debug_id, why, call->cid, call->call_id, seq,
73*0b9bb322SDavid Howells 			  abort_code, error);
74*0b9bb322SDavid Howells 	return __rxrpc_set_call_completion(call, RXRPC_CALL_LOCALLY_ABORTED,
75*0b9bb322SDavid Howells 					   abort_code, error);
76*0b9bb322SDavid Howells }
77*0b9bb322SDavid Howells 
78*0b9bb322SDavid Howells bool rxrpc_abort_call(struct rxrpc_call *call, rxrpc_seq_t seq,
79*0b9bb322SDavid Howells 		      u32 abort_code, int error, enum rxrpc_abort_reason why)
80*0b9bb322SDavid Howells {
81*0b9bb322SDavid Howells 	bool ret;
82*0b9bb322SDavid Howells 
83*0b9bb322SDavid Howells 	write_lock(&call->state_lock);
84*0b9bb322SDavid Howells 	ret = __rxrpc_abort_call(call, seq, abort_code, error, why);
85*0b9bb322SDavid Howells 	write_unlock(&call->state_lock);
86*0b9bb322SDavid Howells 	if (ret && test_bit(RXRPC_CALL_EXPOSED, &call->flags))
87*0b9bb322SDavid Howells 		rxrpc_send_abort_packet(call);
88*0b9bb322SDavid Howells 	return ret;
89*0b9bb322SDavid Howells }
90