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 */
13bool 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 */
35bool 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 */
43bool 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 */
60void 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