190 lines · 6.0 KB · C
RawDownload
/* SPDX-License-Identifier: GPL-2.0+ *//* * SSH packet transport layer. * * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com> */ #ifndef _SURFACE_AGGREGATOR_SSH_PACKET_LAYER_H#define _SURFACE_AGGREGATOR_SSH_PACKET_LAYER_H #include <linux/atomic.h>#include <linux/kfifo.h>#include <linux/ktime.h>#include <linux/list.h>#include <linux/serdev.h>#include <linux/spinlock.h>#include <linux/types.h>#include <linux/wait.h>#include <linux/workqueue.h> #include <linux/surface_aggregator/serial_hub.h>#include "ssh_parser.h" /** * enum ssh_ptl_state_flags - State-flags for &struct ssh_ptl. * * @SSH_PTL_SF_SHUTDOWN_BIT: *	Indicates that the packet transport layer has been shut down or is *	being shut down and should not accept any new packets/data. */enum ssh_ptl_state_flags {	SSH_PTL_SF_SHUTDOWN_BIT,}; /** * struct ssh_ptl_ops - Callback operations for packet transport layer. * @data_received: Function called when a data-packet has been received. Both, *                 the packet layer on which the packet has been received and *                 the packet's payload data are provided to this function. */struct ssh_ptl_ops {	void (*data_received)(struct ssh_ptl *p, const struct ssam_span *data);}; /** * struct ssh_ptl - SSH packet transport layer. * @serdev:        Serial device providing the underlying data transport. * @state:         State(-flags) of the transport layer. * @queue:         Packet submission queue. * @queue.lock:    Lock for modifying the packet submission queue. * @queue.head:    List-head of the packet submission queue. * @pending:       Set/list of pending packets. * @pending.lock:  Lock for modifying the pending set. * @pending.head:  List-head of the pending set/list. * @pending.count: Number of currently pending packets. * @tx:            Transmitter subsystem. * @tx.running:    Flag indicating (desired) transmitter thread state. * @tx.thread:     Transmitter thread. * @tx.thread_cplt_tx:  Completion for transmitter thread waiting on transfer. * @tx.thread_cplt_pkt: Completion for transmitter thread waiting on packets. * @tx.packet_wq:  Waitqueue-head for packet transmit completion. * @rx:            Receiver subsystem. * @rx.thread:     Receiver thread. * @rx.wq:         Waitqueue-head for receiver thread. * @rx.fifo:       Buffer for receiving data/pushing data to receiver thread. * @rx.buf:        Buffer for evaluating data on receiver thread. * @rx.blocked:    List of recent/blocked sequence IDs to detect retransmission. * @rx.blocked.seqs:   Array of blocked sequence IDs. * @rx.blocked.offset: Offset indicating where a new ID should be inserted. * @rtx_timeout:   Retransmission timeout subsystem. * @rtx_timeout.lock:    Lock for modifying the retransmission timeout reaper. * @rtx_timeout.timeout: Timeout interval for retransmission. * @rtx_timeout.expires: Time specifying when the reaper work is next scheduled. * @rtx_timeout.reaper:  Work performing timeout checks and subsequent actions. * @ops:           Packet layer operations. */struct ssh_ptl {	struct serdev_device *serdev;	unsigned long state; 	struct {		spinlock_t lock;		struct list_head head;	} queue; 	struct {		spinlock_t lock;		struct list_head head;		atomic_t count;	} pending; 	struct {		atomic_t running;		struct task_struct *thread;		struct completion thread_cplt_tx;		struct completion thread_cplt_pkt;		struct wait_queue_head packet_wq;	} tx; 	struct {		struct task_struct *thread;		struct wait_queue_head wq;		struct kfifo fifo;		struct sshp_buf buf; 		struct {			u16 seqs[8];			u16 offset;		} blocked;	} rx; 	struct {		spinlock_t lock;		ktime_t timeout;		ktime_t expires;		struct delayed_work reaper;	} rtx_timeout; 	struct ssh_ptl_ops ops;}; #define __ssam_prcond(func, p, fmt, ...)		\	do {						\		typeof(p) __p = (p);			\							\		if (__p)				\			func(__p, fmt, ##__VA_ARGS__);	\	} while (0) #define ptl_dbg(p, fmt, ...)  dev_dbg(&(p)->serdev->dev, fmt, ##__VA_ARGS__)#define ptl_info(p, fmt, ...) dev_info(&(p)->serdev->dev, fmt, ##__VA_ARGS__)#define ptl_warn(p, fmt, ...) dev_warn(&(p)->serdev->dev, fmt, ##__VA_ARGS__)#define ptl_err(p, fmt, ...)  dev_err(&(p)->serdev->dev, fmt, ##__VA_ARGS__)#define ptl_dbg_cond(p, fmt, ...) __ssam_prcond(ptl_dbg, p, fmt, ##__VA_ARGS__) #define to_ssh_ptl(ptr, member) \	container_of(ptr, struct ssh_ptl, member) int ssh_ptl_init(struct ssh_ptl *ptl, struct serdev_device *serdev,		 struct ssh_ptl_ops *ops); void ssh_ptl_destroy(struct ssh_ptl *ptl); /** * ssh_ptl_get_device() - Get device associated with packet transport layer. * @ptl: The packet transport layer. * * Return: Returns the device on which the given packet transport layer builds * upon. */static inline struct device *ssh_ptl_get_device(struct ssh_ptl *ptl){	return ptl->serdev ? &ptl->serdev->dev : NULL;} int ssh_ptl_tx_start(struct ssh_ptl *ptl);int ssh_ptl_tx_stop(struct ssh_ptl *ptl);int ssh_ptl_rx_start(struct ssh_ptl *ptl);int ssh_ptl_rx_stop(struct ssh_ptl *ptl);void ssh_ptl_shutdown(struct ssh_ptl *ptl); int ssh_ptl_submit(struct ssh_ptl *ptl, struct ssh_packet *p);void ssh_ptl_cancel(struct ssh_packet *p); ssize_t ssh_ptl_rx_rcvbuf(struct ssh_ptl *ptl, const u8 *buf, size_t n); /** * ssh_ptl_tx_wakeup_transfer() - Wake up packet transmitter thread for * transfer. * @ptl: The packet transport layer. * * Wakes up the packet transmitter thread, notifying it that the underlying * transport has more space for data to be transmitted. If the packet * transport layer has been shut down, calls to this function will be ignored. */static inline void ssh_ptl_tx_wakeup_transfer(struct ssh_ptl *ptl){	if (test_bit(SSH_PTL_SF_SHUTDOWN_BIT, &ptl->state))		return; 	complete(&ptl->tx.thread_cplt_tx);} void ssh_packet_init(struct ssh_packet *packet, unsigned long type,		     u8 priority, const struct ssh_packet_ops *ops); int ssh_ctrl_packet_cache_init(void);void ssh_ctrl_packet_cache_destroy(void); #endif /* _SURFACE_AGGREGATOR_SSH_PACKET_LAYER_H */