10b9bb322SDavid Howells // SPDX-License-Identifier: GPL-2.0-or-later 20b9bb322SDavid Howells /* Call state changing functions. 30b9bb322SDavid Howells * 40b9bb322SDavid Howells * Copyright (C) 2022 Red Hat, Inc. All Rights Reserved. 50b9bb322SDavid Howells * Written by David Howells (dhowells@redhat.com) 60b9bb322SDavid Howells */ 70b9bb322SDavid Howells 80b9bb322SDavid Howells #include "ar-internal.h" 90b9bb322SDavid Howells 100b9bb322SDavid Howells /* 110b9bb322SDavid Howells * Transition a call to the complete state. 120b9bb322SDavid Howells */ 130b9bb322SDavid Howells bool rxrpc_set_call_completion(struct rxrpc_call *call, 140b9bb322SDavid Howells enum rxrpc_call_completion compl, 150b9bb322SDavid Howells u32 abort_code, 160b9bb322SDavid Howells int error) 170b9bb322SDavid Howells { 18*96b4059fSDavid Howells if (__rxrpc_call_state(call) == RXRPC_CALL_COMPLETE) 19*96b4059fSDavid Howells return false; 200b9bb322SDavid Howells 21*96b4059fSDavid Howells call->abort_code = abort_code; 22*96b4059fSDavid Howells call->error = error; 23*96b4059fSDavid Howells call->completion = compl; 24*96b4059fSDavid Howells /* Allow reader of completion state to operate locklessly */ 25*96b4059fSDavid Howells rxrpc_set_call_state(call, RXRPC_CALL_COMPLETE); 26*96b4059fSDavid Howells trace_rxrpc_call_complete(call); 27*96b4059fSDavid Howells wake_up(&call->waitq); 28*96b4059fSDavid Howells rxrpc_notify_socket(call); 29*96b4059fSDavid Howells return true; 300b9bb322SDavid Howells } 310b9bb322SDavid Howells 320b9bb322SDavid Howells /* 330b9bb322SDavid Howells * Record that a call successfully completed. 340b9bb322SDavid Howells */ 350b9bb322SDavid Howells bool rxrpc_call_completed(struct rxrpc_call *call) 360b9bb322SDavid Howells { 37*96b4059fSDavid Howells return rxrpc_set_call_completion(call, RXRPC_CALL_SUCCEEDED, 0, 0); 380b9bb322SDavid Howells } 390b9bb322SDavid Howells 400b9bb322SDavid Howells /* 410b9bb322SDavid Howells * Record that a call is locally aborted. 420b9bb322SDavid Howells */ 43*96b4059fSDavid Howells bool rxrpc_abort_call(struct rxrpc_call *call, rxrpc_seq_t seq, 440b9bb322SDavid Howells u32 abort_code, int error, enum rxrpc_abort_reason why) 450b9bb322SDavid Howells { 460b9bb322SDavid Howells trace_rxrpc_abort(call->debug_id, why, call->cid, call->call_id, seq, 470b9bb322SDavid Howells abort_code, error); 48*96b4059fSDavid Howells if (!rxrpc_set_call_completion(call, RXRPC_CALL_LOCALLY_ABORTED, 49*96b4059fSDavid Howells abort_code, error)) 50*96b4059fSDavid Howells return false; 51*96b4059fSDavid Howells if (test_bit(RXRPC_CALL_EXPOSED, &call->flags)) 52*96b4059fSDavid Howells rxrpc_send_abort_packet(call); 53*96b4059fSDavid Howells return true; 540b9bb322SDavid Howells } 550b9bb322SDavid Howells 56*96b4059fSDavid Howells /* 57*96b4059fSDavid Howells * Record that a call errored out before even getting off the ground, thereby 58*96b4059fSDavid Howells * setting the state to allow it to be destroyed. 59*96b4059fSDavid Howells */ 60*96b4059fSDavid Howells void rxrpc_prefail_call(struct rxrpc_call *call, enum rxrpc_call_completion compl, 61*96b4059fSDavid Howells int error) 620b9bb322SDavid Howells { 63*96b4059fSDavid Howells call->abort_code = RX_CALL_DEAD; 64*96b4059fSDavid Howells call->error = error; 65*96b4059fSDavid Howells call->completion = compl; 66*96b4059fSDavid Howells call->_state = RXRPC_CALL_COMPLETE; 67*96b4059fSDavid Howells trace_rxrpc_call_complete(call); 68*96b4059fSDavid Howells __set_bit(RXRPC_CALL_RELEASED, &call->flags); 690b9bb322SDavid Howells } 70