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