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