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 } 91