linux/drivers/platform/surface/aggregator/ssh_request_layer.c

// SPDX-License-Identifier: GPL-2.0+
/*
 * SSH request transport layer.
 *
 * Copyright (C) 2019-2022 Maximilian Luz <[email protected]>
 */

#include <asm/unaligned.h>
#include <linux/atomic.h>
#include <linux/completion.h>
#include <linux/error-injection.h>
#include <linux/ktime.h>
#include <linux/limits.h>
#include <linux/list.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/types.h>
#include <linux/workqueue.h>

#include <linux/surface_aggregator/serial_hub.h>
#include <linux/surface_aggregator/controller.h>

#include "ssh_packet_layer.h"
#include "ssh_request_layer.h"

#include "trace.h"

/*
 * SSH_RTL_REQUEST_TIMEOUT - Request timeout.
 *
 * Timeout as ktime_t delta for request responses. If we have not received a
 * response in this time-frame after finishing the underlying packet
 * transmission, the request will be completed with %-ETIMEDOUT as status
 * code.
 */
#define SSH_RTL_REQUEST_TIMEOUT

/*
 * SSH_RTL_REQUEST_TIMEOUT_RESOLUTION - Request timeout granularity.
 *
 * Time-resolution for timeouts. Should be larger than one jiffy to avoid
 * direct re-scheduling of reaper work_struct.
 */
#define SSH_RTL_REQUEST_TIMEOUT_RESOLUTION

/*
 * SSH_RTL_MAX_PENDING - Maximum number of pending requests.
 *
 * Maximum number of requests concurrently waiting to be completed (i.e.
 * waiting for the corresponding packet transmission to finish if they don't
 * have a response or waiting for a response if they have one).
 */
#define SSH_RTL_MAX_PENDING

/*
 * SSH_RTL_TX_BATCH - Maximum number of requests processed per work execution.
 * Used to prevent livelocking of the workqueue. Value chosen via educated
 * guess, may be adjusted.
 */
#define SSH_RTL_TX_BATCH

#ifdef CONFIG_SURFACE_AGGREGATOR_ERROR_INJECTION

/**
 * ssh_rtl_should_drop_response() - Error injection hook to drop request
 * responses.
 *
 * Useful to cause request transmission timeouts in the driver by dropping the
 * response to a request.
 */
static noinline bool ssh_rtl_should_drop_response(void)
{}
ALLOW_ERROR_INJECTION();

#else

static inline bool ssh_rtl_should_drop_response(void)
{
	return false;
}

#endif

static u16 ssh_request_get_rqid(struct ssh_request *rqst)
{}

static u32 ssh_request_get_rqid_safe(struct ssh_request *rqst)
{}

static void ssh_rtl_queue_remove(struct ssh_request *rqst)
{}

static bool ssh_rtl_queue_empty(struct ssh_rtl *rtl)
{}

static void ssh_rtl_pending_remove(struct ssh_request *rqst)
{}

static int ssh_rtl_tx_pending_push(struct ssh_request *rqst)
{}

static void ssh_rtl_complete_with_status(struct ssh_request *rqst, int status)
{}

static void ssh_rtl_complete_with_rsp(struct ssh_request *rqst,
				      const struct ssh_command *cmd,
				      const struct ssam_span *data)
{}

static bool ssh_rtl_tx_can_process(struct ssh_request *rqst)
{}

static struct ssh_request *ssh_rtl_tx_next(struct ssh_rtl *rtl)
{}

static int ssh_rtl_tx_try_process_one(struct ssh_rtl *rtl)
{}

static bool ssh_rtl_tx_schedule(struct ssh_rtl *rtl)
{}

static void ssh_rtl_tx_work_fn(struct work_struct *work)
{}

/**
 * ssh_rtl_submit() - Submit a request to the transport layer.
 * @rtl:  The request transport layer.
 * @rqst: The request to submit.
 *
 * Submits a request to the transport layer. A single request may not be
 * submitted multiple times without reinitializing it.
 *
 * Return: Returns zero on success, %-EINVAL if the request type is invalid or
 * the request has been canceled prior to submission, %-EALREADY if the
 * request has already been submitted, or %-ESHUTDOWN in case the request
 * transport layer has been shut down.
 */
int ssh_rtl_submit(struct ssh_rtl *rtl, struct ssh_request *rqst)
{}

static void ssh_rtl_timeout_reaper_mod(struct ssh_rtl *rtl, ktime_t now,
				       ktime_t expires)
{}

static void ssh_rtl_timeout_start(struct ssh_request *rqst)
{}

static void ssh_rtl_complete(struct ssh_rtl *rtl,
			     const struct ssh_command *command,
			     const struct ssam_span *command_data)
{}

static bool ssh_rtl_cancel_nonpending(struct ssh_request *r)
{}

static bool ssh_rtl_cancel_pending(struct ssh_request *r)
{}

/**
 * ssh_rtl_cancel() - Cancel request.
 * @rqst:    The request to cancel.
 * @pending: Whether to also cancel pending requests.
 *
 * Cancels the given request. If @pending is %false, this will not cancel
 * pending requests, i.e. requests that have already been submitted to the
 * packet layer but not been completed yet. If @pending is %true, this will
 * cancel the given request regardless of the state it is in.
 *
 * If the request has been canceled by calling this function, both completion
 * and release callbacks of the request will be executed in a reasonable
 * time-frame. This may happen during execution of this function, however,
 * there is no guarantee for this. For example, a request currently
 * transmitting will be canceled/completed only after transmission has
 * completed, and the respective callbacks will be executed on the transmitter
 * thread, which may happen during, but also some time after execution of the
 * cancel function.
 *
 * Return: Returns %true if the given request has been canceled or completed,
 * either by this function or prior to calling this function, %false
 * otherwise. If @pending is %true, this function will always return %true.
 */
bool ssh_rtl_cancel(struct ssh_request *rqst, bool pending)
{}

static void ssh_rtl_packet_callback(struct ssh_packet *p, int status)
{}

static ktime_t ssh_request_get_expiration(struct ssh_request *r, ktime_t timeout)
{}

static void ssh_rtl_timeout_reap(struct work_struct *work)
{}

static void ssh_rtl_rx_event(struct ssh_rtl *rtl, const struct ssh_command *cmd,
			     const struct ssam_span *data)
{}

static void ssh_rtl_rx_command(struct ssh_ptl *p, const struct ssam_span *data)
{}

static void ssh_rtl_rx_data(struct ssh_ptl *p, const struct ssam_span *data)
{}

static void ssh_rtl_packet_release(struct ssh_packet *p)
{}

static const struct ssh_packet_ops ssh_rtl_packet_ops =;

/**
 * ssh_request_init() - Initialize SSH request.
 * @rqst:  The request to initialize.
 * @flags: Request flags, determining the type of the request.
 * @ops:   Request operations.
 *
 * Initializes the given SSH request and underlying packet. Sets the message
 * buffer pointer to %NULL and the message buffer length to zero. This buffer
 * has to be set separately via ssh_request_set_data() before submission and
 * must contain a valid SSH request message.
 *
 * Return: Returns zero on success or %-EINVAL if the given flags are invalid.
 */
int ssh_request_init(struct ssh_request *rqst, enum ssam_request_flags flags,
		     const struct ssh_request_ops *ops)
{}

/**
 * ssh_rtl_init() - Initialize request transport layer.
 * @rtl:    The request transport layer to initialize.
 * @serdev: The underlying serial device, i.e. the lower-level transport.
 * @ops:    Request transport layer operations.
 *
 * Initializes the given request transport layer and associated packet
 * transport layer. Transmitter and receiver threads must be started
 * separately via ssh_rtl_start(), after the request-layer has been
 * initialized and the lower-level serial device layer has been set up.
 *
 * Return: Returns zero on success and a nonzero error code on failure.
 */
int ssh_rtl_init(struct ssh_rtl *rtl, struct serdev_device *serdev,
		 const struct ssh_rtl_ops *ops)
{}

/**
 * ssh_rtl_destroy() - Deinitialize request transport layer.
 * @rtl: The request transport layer to deinitialize.
 *
 * Deinitializes the given request transport layer and frees resources
 * associated with it. If receiver and/or transmitter threads have been
 * started, the layer must first be shut down via ssh_rtl_shutdown() before
 * this function can be called.
 */
void ssh_rtl_destroy(struct ssh_rtl *rtl)
{}

/**
 * ssh_rtl_start() - Start request transmitter and receiver.
 * @rtl: The request transport layer.
 *
 * Return: Returns zero on success, a negative error code on failure.
 */
int ssh_rtl_start(struct ssh_rtl *rtl)
{}

struct ssh_flush_request {};

static void ssh_rtl_flush_request_complete(struct ssh_request *r,
					   const struct ssh_command *cmd,
					   const struct ssam_span *data,
					   int status)
{}

static void ssh_rtl_flush_request_release(struct ssh_request *r)
{}

static const struct ssh_request_ops ssh_rtl_flush_request_ops =;

/**
 * ssh_rtl_flush() - Flush the request transport layer.
 * @rtl:     request transport layer
 * @timeout: timeout for the flush operation in jiffies
 *
 * Queue a special flush request and wait for its completion. This request
 * will be completed after all other currently queued and pending requests
 * have been completed. Instead of a normal data packet, this request submits
 * a special flush packet, meaning that upon completion, also the underlying
 * packet transport layer has been flushed.
 *
 * Flushing the request layer guarantees that all previously submitted
 * requests have been fully completed before this call returns. Additionally,
 * flushing blocks execution of all later submitted requests until the flush
 * has been completed.
 *
 * If the caller ensures that no new requests are submitted after a call to
 * this function, the request transport layer is guaranteed to have no
 * remaining requests when this call returns. The same guarantee does not hold
 * for the packet layer, on which control packets may still be queued after
 * this call.
 *
 * Return: Returns zero on success, %-ETIMEDOUT if the flush timed out and has
 * been canceled as a result of the timeout, or %-ESHUTDOWN if the packet
 * and/or request transport layer has been shut down before this call. May
 * also return %-EINTR if the underlying packet transmission has been
 * interrupted.
 */
int ssh_rtl_flush(struct ssh_rtl *rtl, unsigned long timeout)
{}

/**
 * ssh_rtl_shutdown() - Shut down request transport layer.
 * @rtl: The request transport layer.
 *
 * Shuts down the request transport layer, removing and canceling all queued
 * and pending requests. Requests canceled by this operation will be completed
 * with %-ESHUTDOWN as status. Receiver and transmitter threads will be
 * stopped, the lower-level packet layer will be shutdown.
 *
 * As a result of this function, the transport layer will be marked as shut
 * down. Submission of requests after the transport layer has been shut down
 * will fail with %-ESHUTDOWN.
 */
void ssh_rtl_shutdown(struct ssh_rtl *rtl)
{}