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