162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* Call state changing functions. 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright (C) 2022 Red Hat, Inc. All Rights Reserved. 562306a36Sopenharmony_ci * Written by David Howells (dhowells@redhat.com) 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include "ar-internal.h" 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci/* 1162306a36Sopenharmony_ci * Transition a call to the complete state. 1262306a36Sopenharmony_ci */ 1362306a36Sopenharmony_cibool rxrpc_set_call_completion(struct rxrpc_call *call, 1462306a36Sopenharmony_ci enum rxrpc_call_completion compl, 1562306a36Sopenharmony_ci u32 abort_code, 1662306a36Sopenharmony_ci int error) 1762306a36Sopenharmony_ci{ 1862306a36Sopenharmony_ci if (__rxrpc_call_state(call) == RXRPC_CALL_COMPLETE) 1962306a36Sopenharmony_ci return false; 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci call->abort_code = abort_code; 2262306a36Sopenharmony_ci call->error = error; 2362306a36Sopenharmony_ci call->completion = compl; 2462306a36Sopenharmony_ci /* Allow reader of completion state to operate locklessly */ 2562306a36Sopenharmony_ci rxrpc_set_call_state(call, RXRPC_CALL_COMPLETE); 2662306a36Sopenharmony_ci trace_rxrpc_call_complete(call); 2762306a36Sopenharmony_ci wake_up(&call->waitq); 2862306a36Sopenharmony_ci rxrpc_notify_socket(call); 2962306a36Sopenharmony_ci return true; 3062306a36Sopenharmony_ci} 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci/* 3362306a36Sopenharmony_ci * Record that a call successfully completed. 3462306a36Sopenharmony_ci */ 3562306a36Sopenharmony_cibool rxrpc_call_completed(struct rxrpc_call *call) 3662306a36Sopenharmony_ci{ 3762306a36Sopenharmony_ci return rxrpc_set_call_completion(call, RXRPC_CALL_SUCCEEDED, 0, 0); 3862306a36Sopenharmony_ci} 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci/* 4162306a36Sopenharmony_ci * Record that a call is locally aborted. 4262306a36Sopenharmony_ci */ 4362306a36Sopenharmony_cibool rxrpc_abort_call(struct rxrpc_call *call, rxrpc_seq_t seq, 4462306a36Sopenharmony_ci u32 abort_code, int error, enum rxrpc_abort_reason why) 4562306a36Sopenharmony_ci{ 4662306a36Sopenharmony_ci trace_rxrpc_abort(call->debug_id, why, call->cid, call->call_id, seq, 4762306a36Sopenharmony_ci abort_code, error); 4862306a36Sopenharmony_ci if (!rxrpc_set_call_completion(call, RXRPC_CALL_LOCALLY_ABORTED, 4962306a36Sopenharmony_ci abort_code, error)) 5062306a36Sopenharmony_ci return false; 5162306a36Sopenharmony_ci if (test_bit(RXRPC_CALL_EXPOSED, &call->flags)) 5262306a36Sopenharmony_ci rxrpc_send_abort_packet(call); 5362306a36Sopenharmony_ci return true; 5462306a36Sopenharmony_ci} 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci/* 5762306a36Sopenharmony_ci * Record that a call errored out before even getting off the ground, thereby 5862306a36Sopenharmony_ci * setting the state to allow it to be destroyed. 5962306a36Sopenharmony_ci */ 6062306a36Sopenharmony_civoid rxrpc_prefail_call(struct rxrpc_call *call, enum rxrpc_call_completion compl, 6162306a36Sopenharmony_ci int error) 6262306a36Sopenharmony_ci{ 6362306a36Sopenharmony_ci call->abort_code = RX_CALL_DEAD; 6462306a36Sopenharmony_ci call->error = error; 6562306a36Sopenharmony_ci call->completion = compl; 6662306a36Sopenharmony_ci call->_state = RXRPC_CALL_COMPLETE; 6762306a36Sopenharmony_ci trace_rxrpc_call_complete(call); 6862306a36Sopenharmony_ci WARN_ON_ONCE(__test_and_set_bit(RXRPC_CALL_RELEASED, &call->flags)); 6962306a36Sopenharmony_ci} 70